描述一下您用于 Java Web 应用程序的体系结构?[已关闭]体系结构概述架构的优缺点网页层 :RESTFul Web控制器/操作/请求处理层:业务逻辑/服务层:XML/JSon 数据转换层:持久层 :

2022-08-31 07:43:00

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

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

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

我会开始...


体系结构概述

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

  • 坚持
  • 介绍

各层之间可能的通信流由以下方式表示:

Persistence <-> Business <-> Presentation

例如,这意味着表示层从不调用或执行持久性操作,它始终通过业务层执行此操作。此体系结构旨在满足高可用性 Web 应用程序的需求。

坚持

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

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

此外,该层还存储 JPA 实体,例如 等。AccountShoppingCart

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

此层分为多个类,每个类都带有注释,以成为无状态会话 Bean (SLSB)。每个 SLSB 都称为管理器,例如,管理器可以是一个带注释的类,如前所述,称为 。@StatelessAccountManager

当需要执行 CRUD 操作时,它会对 的实例进行适当的调用,该实例是持久化层中的一个类。其中两种方法的粗略草图可以是:AccountManagerAccountManagerPersistenceAccountManager

...
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
}

我们使用容器管理器事务,因此我们不必进行事务划分。在后台基本上发生的事情是,我们在进入SLSB方法时启动一个事务,并在退出方法之前立即提交它(或回滚它)。这是约定胜过配置的一个例子,但除了默认的“必需”之外,我们不需要任何东西。

以下是 Sun 的 Java EE 5 教程如何解释 Enterprise JavaBeans (EJB) 的必需事务属性

如果客户端在事务中运行并调用企业 Bean 的方法,则该方法将在客户端的事务中执行。如果客户端未与事务关联,容器将在运行该方法之前启动新事务。

Required 属性是使用容器管理的事务划分运行的所有企业 Bean 方法的隐式事务属性。通常不设置 Required 属性,除非需要覆盖另一个事务属性。由于事务属性是声明性的,因此您可以在以后轻松更改它们。

介绍

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

该层调用业务层管理器中的方法,以执行用户请求的操作并接收要在网页中显示的信息。有时,从业务层接收到的信息是不太复杂的类型,如 和 egers,有时是 JPA 实体Stringint

架构的优缺点

优点

  • 拥有与在此层中执行持久性的特定方式相关的所有内容仅意味着我们可以从使用JPA切换到其他内容,而不必在业务层中重写任何内容。
  • 我们很容易将表示层交换成其他东西,如果我们找到更好的东西,我们很可能会这样做。
  • 让 EJB 容器管理事务边界很不错。
  • 使用Servlet的+ JPA很容易(一开始),这些技术在许多服务器中被广泛使用和实现。
  • 使用Java EE应该使我们能够更轻松地创建具有负载平衡和故障转移功能的高可用性系统。这两者我们都觉得我们必须拥有。

缺点

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

答案 1

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

  • 前端:Tapestry(旧项目3个,新项目5个)
  • 业务层:弹簧
  • DAO's : 伊巴蒂斯
  • 数据库 : 甲骨文

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

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

在我们的例子中使用Spring的优点是,我们可以拥有依赖于国家/语言的实例,这些实例位于Spring代理类后面。根据会话中的用户,在执行呼叫时使用正确的国家/语言实现。

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

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


答案 2

当今理想的基于Java的Web开发技术。

网页层 :

HTML+CSS+Ajax+JQuery

RESTFul Web控制器/操作/请求处理层:

游戏框架

业务逻辑/服务层:

尽可能长时间地使用纯 Java 代码。人们可以在这里进行Web服务的融合。

XML/JSon 数据转换层:

XMLTool(Search On Google Code),JSoup,Google GSon,XStream,JOOX (Search On Google Code)

持久层 :

CRUD : JPA 或 SienaProject 或 QueryDSL / Complex Queries : JOOQ,QueryDSL


推荐