让我们分享基于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实体哪些是喜欢的东西Account,ShoppingCart等等。
Account
ShoppingCart
与Web应用程序功能相关的所有逻辑均位于此层。此功能可能是为想要使用她/他的信用卡在线购买产品的客户发起汇款。也可能是在基于网络的游戏中创建新用户,删除用户或计算战斗结果。
该层分为多个类,每个类都带有注释,@Stateless以成为无状态会话Bean(SLSB)。每个SLSB都称为_管理器_ ,例如,管理器可以是带有注释的类,称为AccountManager。
@Stateless
AccountManager
当AccountManager需要执行CRUD操作时,它将对实例进行适当的调用,该实例AccountManagerPersistence是持久层中的类。两种方法的大致草图AccountManager可能是:
AccountManagerPersistence
... 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属性。因为事务属性是声明性的,所以以后可以轻松更改它们。
如果客户端在事务中运行并调用企业bean的方法,则该方法在客户端的事务中执行。如果客户端未与事务关联,则容器在运行该方法之前启动一个新事务。
Required属性是使用容器管理的事务划分运行的所有企业Bean方法的隐式事务属性。除非您需要覆盖另一个事务属性,否则通常不设置Required属性。因为事务属性是声明性的,所以以后可以轻松更改它们。
我们的演示层负责…演示!它负责用户界面,并通过构建HTML页面并通过GET和POST请求接收用户输入来向用户显示信息。我们目前正在使用旧的Servlet + Java Server Pages(JSP)组合。
该层调用业务层 管理器 中的方法以执行用户请求的操作并接收要在网页中显示的信息。有时,从业务层接收到的信息是不太复杂的类型,String年代和integers,并在其他时间JPA实体。
String
int
@NamedQuery
fetch=FetchType.LAZY
FETCH JOIN
好吧,我将做一个(简短的):
我们使用Sping事务支持,并在进入服务层后开始事务,扩展到DAO调用。服务层具有最强的业务模型知识,而DAO则进行相对简单的CRUD工作。
出于性能原因,一些更复杂的查询内容由后端中的更复杂的查询处理。
在我们的案例中使用Spring的优点是我们可以拥有依赖于国家/语言的实例,这些实例在Spring Proxy类的后面。根据会话中的用户,在进行呼叫时将使用正确的国家(地区)/语言实现。
事务管理几乎是透明的,可以在运行时异常上回滚。我们尽可能使用未检查的异常。我们曾经做过检查异常,但是随着Spring的引入,我看到了非检查异常的好处,只有在可以的情况下才处理异常。它避免了很多样板“捕获/抛出”或“抛出”的东西。
抱歉,它比您的帖子短,希望您发现这个有趣的话题…