描述你用于 JavaWeb 应用程序的体系结构?

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

Web 应用程序有很多不同的体系结构,这些体系结构都是用 Java 实现的。这个问题的答案可以作为各种 Web 应用程序设计及其优缺点的库。虽然我知道答案是主观的,但是让我们尽可能的客观,并且激发我们列出的优点和缺点。

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

我从..。


体系结构概述

我们使用一个基于开放标准的三层架构,这些标准来自于 Sun,比如 JavaEE、 Java持久化API、 Servlet 和 Java 服务器页面。

  • 坚持不懈
  • 生意
  • 展示

各层之间可能的通信流程表现为:

Persistence <-> Business <-> Presentation

例如,这意味着表示层从不调用或执行持久化操作,它总是通过业务层执行。这个架构是为了满足一个高可用性的 web 应用程序的需求。

坚持不懈

执行创建、读取、更新和删除(讨厌)持久化操作。在我们的示例中,我们使用(Java持久化API) JPA,目前使用 冬眠作为持久性提供程序,并使用 它的 EntityManager

这一层被划分为多个类,其中每个类处理特定类型的实体(即与购物车相关的实体可能由一个持久性类处理) ,并且 用过由一个且仅由一个 经理处理。

此外,这一层也存储 JPA 实体的事情,如 AccountShoppingCart等。

生意

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

该层被划分为多个类,每个类都用 @Stateless进行注释,从而成为一个 无状态会话 Bean(SLSB)。每个 SLSB 称为 经理,例如,一个管理器可以是一个被注释为 AccountManager的类。

AccountManager需要执行 CRUD 操作时,它对 AccountManagerPersistence的实例进行适当的调用,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 的 JavaEE 5教程如何解释 EJB (EJB)的 必需的事务属性:

如果客户端在 事务并调用企业 Bean 的方法,则执行该方法 在客户的交易。如果 客户端与 事务时,容器启动一个 在运行 方法。

“必需”属性是隐式的 所有的事务属性 运行的企业 bean 方法 容器管理的事务 你通常不设置 必需属性,除非您需要 重写另一个交易 属性。因为交易 属性是声明性的,您可以 很容易改变他们以后。

展示

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

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

架构的利与弊

优点

  • 在这个层中拥有一切与执行持久性的特定方法相关的内容,只意味着我们可以从使用 JPA 转换到其他内容,而不必在业务层中重写任何内容。
  • It's easy for us to swap our presentation layer into something else, and it's likely that we will if we find something better.
  • 让 EJB 容器管理事务边界是很好的。
  • 使用 Servlet 的 + JPA 很容易(一开始) ,而且这些技术在许多服务器中得到了广泛的应用和实现。
  • 使用 Java EE 应该可以让我们更容易地用 负载平衡负载平衡故障转移创建一个高可用性系统。我们觉得我们必须拥有这两样东西。

缺点

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

好吧,我来做一个(短一点的) :

  • 前端: 挂毯(旧项目3个,新项目5个)
  • 业务层: Spring
  • Ibatis
  • 数据库: Oracle

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

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

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

事务管理几乎是透明的,回滚运行时异常。我们尽可能多地使用未检查的异常。我们过去常常检查异常,但是随着 Spring 的引入,我看到了未检查异常的好处,只有在可以的时候才处理异常。它避免了许多样式化的“捕捉/重新抛出”或“抛出”的东西。

对不起,它比你的职位短,希望你觉得这个有趣..。

我们仍然使用通常的 Struts-Spring-Hibernate 堆栈。

对于未来的应用程序,我们正在研究 Spring Web Flow + Spring MVC + Hibernate 或 Spring + Hibernate + 具有 Flex 前端的 Web 服务。

我们的体系结构的一个显著特点是模块化。我们有许多模块,有些从数据库中的3到最多30个表开始。大多数模块由业务和网络项目组成。业务项目持有业务和持久性逻辑,而 Web 持有表示逻辑。
在逻辑层次上,有三个层次: 业务、持久性和表示。
依赖性:
表示依赖于业务和持久性。
持久性取决于业务。
业务不依赖于其他层。

大多数业务项目都有三种类型的接口(注意: 不是 GUI,而是一个可编程的 Java 接口层)。

  1. 表示形式作为客户端使用的接口
  2. 其他模块作为模块的客户端时正在使用的接口。
  3. 接口,该接口可用于模块的管理目的。

通常,1延伸为2。 通过这种方式,可以很容易地将模块的一个实现替换为另一个实现。这有助于我们适应不同的客户和更容易地集成。一些客户将只购买某些模块,我们需要集成他们已经拥有的功能。由于接口和实现层是分开的,所以很容易为特定客户端推出 ad-hock 模块实现,而不会影响依赖模块。Spring 框架使得注入不同的实现变得很容易。

我们的业务层基于 POJO。我观察到的一个趋势是,这些 POJO 类似于 DTO。我们患有 贫血领域模型贫血领域模型。我不太确定为什么会发生这种情况,但是这可能是由于我们的许多模块的问题域的简单性,大部分工作是 CRUD 或者是由于开发人员喜欢把逻辑放在其他地方。

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

网页层:

HTML + CSS + 一个 jax + JQuery

RESTFull Web 控制器/动作/请求处理层:

播放框架

业务逻辑/服务层:

尽可能长时间地使用纯 Java 代码。

XML/JSon 数据转换层:

XMLTool (Google 代码搜索) ,JSoup,Google GSon,XStream,JOOX (Google 代码搜索)

持久层:

CRUD: JPA 或 SienaProject 或 QueryDSL/ 复杂查询: JOOQ,QueryDSL

我曾经参与过一些项目,这些项目采用了严格的管理者模式。从历史上看,我是严格等级制度的坚定支持者,在这种制度下,所有的东西都被装进一个整洁的盒子里。随着我职业生涯的发展,我发现在很多情况下这是被迫的。我相信,对应用程序设计采用更加敏捷的思维方式会产生更好的产品。我所说的创建一组解决手头问题的类是什么意思。而不是说“你为这个和那个建立了一个经理吗?”

我目前正在做的项目是一个 Web 应用程序,它结合了 Spring MVC 和 RestEasy JSON/Ajax 调用。在我们的控制器中嵌入的服务器端是一个合理的基于 facade 的数据层,带有 JPA/Hibernate,用于直接数据库访问、一些 EJB 访问和一些基于 SOAP 的 Web 服务调用。将所有这些结合在一起的是一些定制的 Java 控制器代码,它们决定将什么序列化为 JSON 并返回给客户机。

我们几乎没有花时间去尝试创建一些统一的模式,而是选择采用 Unix 设计哲学中的“更差就是更好”的理念。因为它是更好的颜色以外的线条和建立一些明智的,快于建立一些东西,坚持一堆严格的设计任务。

恕我直言,我们大多数人都有一个共同点。至少在后端,我们有某种形式的 IOC/DI 容器和一个持久化框架。我个人使用 Guice 和 Mybatis。区别在于我们如何实现视图/UI/表示层。这里有两个主要的选择(可能更多)。.基于操作(映射到控制器的 URL)和基于组件的。目前正在使用基于组件的表示层(使用 wicket)。它完美地模拟了我使用组件和事件而不是 URL 和控制器的桌面环境。我目前正在寻找一个原因,为什么我应该迁移到这个 URL 控制器类型的架构(这就是我如何结束在这个页面)。为什么大肆宣传 RESTful 和无状态架构。

简而言之,我使用面向组件的框架在 Guice IOC 容器上编写有状态的 web 应用程序,并使用 Mybatis 将数据放入关系数据库中。

有点不同,我认为这里有更多的模块化 Java 架构。我们有:

  1. Spring WS/Rest/JSP 前端
  2. Spring MVC 用于业务服务逻辑,包含表示层逻辑和 Spring 事务
  3. 组件服务通信接口,通过业务服务查找 EJB。EJB 设置自己的事务边界,以便能够加入 Spring 事务。
  4. 组件服务实现,同样是 Spring 组件
  5. 集成层,用于数据库集成的 MyBatis,用于 Web 服务集成的 Spring WS,用于其他服务的其他集成技术
  6. 主机,数据库,其他服务器上的其他服务..。

除此之外,我们还有共享库模块,它是所有服务的通用功能提供者。

使用不同的层允许我们完全解耦和我们需要的模块化。我们还能够充分利用 JavaEE 和 Spring 的能力。没有什么可以阻止我们使用 JSF,例如,如果需要的话,用于前端。

与 OP 的示例架构相比,我认为这可以被描述为有四个主要层而不是三个,尽管有一些变化。

这是我的5分钱

展示

Android,Angular. JS WebClient,OAUTHv2

空气污染指数

REST、 Jersey (JAX-RS)、 Jackson (JSON 反/序列化)、 DTO 对象(不同于业务逻辑模型)

业务逻辑

用于 DI 和事件处理的 Spring。模型对象的 DDD 式方法。较长时间运行的作业在 worker 模块中用 SQS 卸载。

DAO

使用 SpringJDBC 模板存储实体的存储库模型。 使用有序列表的排行榜 Redis (JEDIS)。 令牌存储的 Memcache。

数据库

MySQL,Memcached,Redis

Web 应用程序体系结构的组成部分包括:

第1集: 浏览器: 客户端交互

        HTML
JavaScript
Stylesheet

2: 互联网

3: 网络服务器

        CSS
Image
Pages(Java render )

4: 应用服务器

        App Webapp (Java interaction)
Others WebApps

5: 数据库服务器

        Oracle, SQL, MySQL

6: 数据

下面是另一个我曾经研究过的网络架构:

一个主要的需求是应用程序应该支持移动/其他 应用程序也应该是可扩展的或灵活的,以 技术选择的变化。

简报级别:

  • JSP/JQuery (客户端 MVC)
  • 原生机器人
  • 土生土长的 iPhone
  • 移动网络(HTML5/CSS3/响应式设计)

  • Spring REST 控制器(可以更改为 JAX-RS)

商务服务层次:

Spring@Service (可以更改为无状态 EJB)

资料存取层:

Spring@Repository (可以更改为 Stateless EJB)

资源层次:

Hibernate (JPA)实体(可以更改为任何 ORM)

您可以在遵循这个架构的书中找到更多的信息 给你

在我们的项目中,我们遵循的是:

前端科技

  • AngularJS
  • HTML5
  • Css3
  • Javascript
  • 鞋带3

空气污染指数

  1. 休息
  2. 泽西(JAX-RS)
  3. 放心吧
  4. 弹簧靴
  5. 杰克逊
  6. 春季保安

业务逻辑

  • 春季数据

  • SPRING 数据 MongoDB

数据库

  • MongoDB

服务器(用于缓存)

  • 雷迪斯