java - 描述您用于 Java Web 应用程序的架构?

标签 java architecture jakarta-ee

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

5年前关闭。



Improve this question




让我们分享基于 Java 的 Web 应用程序架构!

使用 Java 实现的 Web 应用程序有许多不同的体系结构。这个问题的答案可以作为各种 Web 应用程序设计及其优缺点的库。虽然我意识到答案将是主观的,但让我们尽量保持客观并激发我们列出的利弊。

使用您喜欢的详细程度来描述您的架构。为了让您的答案具有任何值(value),您至少必须描述您所描述的架构中使用的主要技术和想法。最后但并非最不重要的一点是,我们什么时候应该使用您的架构?

我会开始...

架构概述

我们使用基于 Sun 开放标准的 3 层架构,如 Java EE、Java Persistence API、Servlet 和 Java Server Pages。

  • 坚持
  • 业务
  • 介绍

  • 层间可能的通信流表示为:
    Persistence <-> Business <-> Presentation
    

    例如,表示层从不调用或执行持久性操作,它总是通过业务层来完成。该架构旨在满足高可用性 Web 应用程序的需求。

    坚持

    执行创建、读取、更新和删除 ( CRUD ) 持久性操作。在我们的例子中,我们使用 ( Java Persistence API ) JPA 并且我们目前使用 Hibernate作为我们的持久性提供者并使用 its EntityManager .

    该层分为多个类,其中每个类处理特定类型的实体(即与购物车相关的实体可能由单个持久性类处理),并且由一个且仅一个管理器使用。

    另外这一层还存储了JPA entities诸如 Account 之类的东西, ShoppingCart等。

    业务

    所有与 Web 应用程序功能相关的逻辑都位于这一层。此功能可以为想要使用她/他的信用卡在线支付产品的客户发起汇款。它也可以是创建新用户、删除用户或计算基于 Web 的游戏中的战斗结果。

    该层分为多个类,每个类都用 @Stateless 注释。成为Stateless Session Bean (SLSB)。每个 SLSB 被称为一个管理器,例如一个管理器可以是一个被注释的类,称为 AccountManager .

    AccountManager需要执行 CRUD 操作,它会对 AccountManagerPersistence 的实例进行适当的调用。 ,它是持久层中的一个类。 AccountManager 中两种方法的粗略草图可能是:
    ...
    public void makeExpiredAccountsInactive() {
        AccountManagerPersistence amp = new AccountManagerPersistence(...)
        // Calls persistence layer
        List<Account> expiredAccounts = amp.getAllExpiredAccounts();
        for(Account account : expiredAccounts) {
            this.makeAccountInactive(account)
        }
    }
    public void makeAccountInactive(Account account) {
        AccountManagerPersistence amp = new AccountManagerPersistence(...)
        account.deactivate();
        amp.storeUpdatedAccount(account); // Calls persistence layer
    }
    

    我们使用 container manager transactions所以我们不必做我们自己的事务划分。在幕后发生的事情是,我们在进入 SLSB 方法时启动一个事务,并在退出该方法之前立即提交(或回滚)它。这是一个约定优于配置的例子,但除了默认的Required,我们还不需要任何东西。

    以下是 Sun 的 Java EE 5 教程如何解释 Required transaction attribute对于 Enterprise JavaBeans (EJB):

    If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.

    The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.



    介绍

    我们的表示层负责……表示!它负责用户界面,并通过构建 HTML 页面和通过 GET 和 POST 请求接收用户输入来向用户显示信息。我们目前使用的是旧版 Servlet 's + Java Server Pages ( JSP ) 组合。

    该层调用业务层管理器中的方法来执行用户请求的操作并接收信息显示在网页中。有时从业务层收到的信息是不太复杂的类型,如 String的和 int egers,其他时间 JPA entities .

    架构的优缺点

    优点
  • 在这一层中拥有与执行持久性的特定方式相关的所有内容仅意味着我们可以从使用 JPA 转换为其他内容,而无需在业务层中重新编写任何内容。
  • 我们很容易将我们的表示层换成其他东西,如果我们找到更好的东西,我们很可能会这样做。
  • 让 EJB 容器管理事务边界很好。
  • 使用 Servlet's + JPA 很容易(开始时),并且这些技术在许多服务器中被广泛使用和实现。
  • 使用 Java EE 应该可以让我们更轻松地使用 load balancing 创建高可用性系统。和 fail over .两者我们都觉得我们必须拥有。

  • 缺点
  • 使用 JPA,您可以使用 @NamedQuery 将经常使用的查询存储为命名查询。 JPA 实体类上的注释。如果您在持久性类中尽可能多地与持久性相关,就像在我们的体系结构中一样,这将分散您可能会发现查询的位置,以包括 JPA 实体。概述持久性操作将更加困难,因此更难维护。
  • 我们将 JPA 实体作为持久层的一部分。但是AccountShoppingCart ,它们真的不是业务对象吗?这样做是因为您必须接触这些类并将它们转换为 JPA 知道如何处理的实体。
  • JPA 实体也是我们的业务对象,其创建方式类似于数据传输对象( DTO ),也称为值对象(VO)。这会导致 anemic domain model因为业务对象除了访问器方法之外没有自己的逻辑。所有逻辑都由我们的业务层经理完成,这导致了更加程序化的编程风格。这不是一个好的面向对象设计,但也许这不是问题? (毕竟面向对象并不是唯一提供结果的编程范式。)
  • 使用 EJB 和 Java EE 会带来一些复杂性。而且我们不能纯粹使用Tomcat(添加EJB微容器不是纯粹的Tomcat)。
  • 使用 Servlet's + JPA 有很多问题。使用 Google 获取有关这些问题的更多信息。
  • 由于事务在退出业务层时关闭,因此我们无法从 JPA 实体加载任何信息,这些信息被配置为在需要时(使用 fetch=FetchType.LAZY)从表示层内部从数据库加载。它会触发异常。在返回包含这些类型字段的实体之前,我们必须确保调用相关的 getter。另一种选择是使用 Java 持久性查询语言 ( JPQL ) 并执行 FETCH JOIN .然而,这两个选项都有点麻烦。
  • 最佳答案

    好的,我会做一个(较短的):

  • 前端:Tapestry (3 个用于旧项目,5 个用于新项目)
  • 业务层:Spring
  • DAO 的:Ibatis
  • 数据库:Oracle

  • 我们使用 Sping 事务支持,并在进入服务层时启动事务,向下传播到 DAO 调用。 Service 层拥有最多的业务模型知识,而 DAO 则做相对简单的 CRUD 工作。

    出于性能原因,一些更复杂的查询内容由后端中更复杂的查询处理。

    在我们的案例中使用 Spring 的优点是我们可以拥有依赖于国家/语言的实例,这些实例位于 Spring Proxy 类之后。根据 session 中的用户,拨打电话时使用正确的国家/地区/语言实现。

    事务管理几乎是透明的,运行时异常回滚。我们尽可能使用未经检查的异常。我们曾经做过受检异常,但是随着 Spring 的引入,我看到了非受检异常的好处,只有在可能的情况下才处理异常。它避免了很多样板“捕获/重新抛出”或“抛出”的东西。

    对不起,它比你的帖子短,希望你觉得这很有趣......

    关于java - 描述您用于 Java Web 应用程序的架构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/286846/

    相关文章:

    java 像素图像处理

    java - Rest 模板与根数组绑定(bind)

    java - 我正在编码以在二维数组中保存和打印 1 ... 10 范围内的素数。

    java - java中的对象身份哈希码

    java - 如何在现有的Java应用程序中做到模块化?

    java - request.getSession().getId() 与 request.getRequestedSessionId()

    java - Hibernate 自动创建数据库

    design-patterns - 领域驱动设计定义的应用程序服务中的数据库事务

    math - block 浮点运算与常规浮点运算

    java - 如何用数据库实现一个完美的队列