一尘不染

描述您用于Java Web应用程序的体系结构?

java

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

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

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

我开始…


体系结构概述

我们使用基于Sun的开放标准(如Java EE,Java Persistence API,Servlet和Java Server
Pages)的三层体系结构。

  • 坚持不懈
  • 商业
  • 介绍

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

Persistence <-> Business <-> Presentation

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

坚持不懈

执行创建,读取,更新和删除(CRUD)持久性操作。在本例中,我们正在使用(Java
Persistence
API
)JPA,并且当前使用Hibernate作为持久性提供程序,并使用其EntityManager

该层分为多个类别,其中有某种类型的实体的每一类交易(涉及到购物车即实体可能是由一个单独的持久类得到处理),并 使用 一个且只有一个 经理

此外,该层还存储JPA实体哪些是喜欢的东西AccountShoppingCart等等。

商业

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

该层分为多个类,每个类都带有注释,@Stateless以成为无状态会话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
}

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

这是Sun的Java EE 5教程解释Enterprise
JavaBeans(EJB)的Required事务属性的方式:

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

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

介绍

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

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

架构的优缺点

优点

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

缺点

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

阅读 244

收藏
2020-12-03

共1个答案

一尘不染

好吧,我将做一个(简短的):

  • 前端:Tapestry(较旧的项目为3个,较新的项目为5个)
  • 业务层:春季
  • DAO’s:Ibatis
  • 数据库:Oracle

我们使用Sping事务支持,并在进入服务层后开始事务,扩展到DAO调用。服务层具有最强的业务模型知识,而DAO则进行相对简单的CRUD工作。

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

在我们的案例中使用Spring的优点是我们可以拥有依赖于国家/语言的实例,这些实例在Spring
Proxy类的后面。根据会话中的用户,在进行呼叫时将使用正确的国家(地区)/语言实现。

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

抱歉,它比您的帖子短,希望您发现这个有趣的话题…

2020-12-03