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


146

让我们分享基于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。但是,这两个选项都比较麻烦。

1
看来您用自己的答案设置的门槛太高了-可能使其他人望而却步:)
约尼克(Jonik)2009年

5
另外,也许您的答案应该是常规答案,而不是问题的一部分,以便可以与其他答案一起投票?
Jonik)

此问题已在meta上引用
D4V1D

Answers:


20

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

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

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

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

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

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

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


好答案!这个线程似乎吸引了一些访问量,可惜其他人没有时间来描述其体系结构,或者有其他不参与的原因。

19

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

网页层:

HTML + CSS + Ajax + JQuery

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

播放框架

业务逻辑/服务层:

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

XML / JSon数据转换层:

XMLTool(在Google Code上搜索),JSoup,Google GSon,XStream,JOOX(在Google Code上搜索)

持久层:

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


9

这是我的五分钱

介绍

Android,Angular.JS WebClient,OAUTHv2

API

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

商业逻辑

用于DI和事件处理的Spring。模型对象的DDD-ish方法。使用工作模块中的SQS可以卸载运行时间更长的作业。

具有用于存储实体的Spring JDBC模板的存储库模型。排行榜的Redis(JEDIS),使用有序列表。令牌存储的内存缓存。

数据库

MySQL,Memcached,Redis


这也与我们在项目中遵循的类似!此外,JBPM用于业务工作流。为什么我没有春天呢?
ininprsr 2015年

我应该对当前的架构进行更新:当前,我们将Spring DI和JDBC模板用于数据访问层。
2015年

6

我们在项目中遵循的是:

前端技术

  • AngularJS
  • HTML5
  • css3
  • Java脚本
  • 引导程序3

API

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

商业逻辑

  • 弹簧数据

  • SPRING数据MongoDB

资料库

  • MongoDB

服务器(用于缓存)

  • Redis

4

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

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

我们架构的一个鲜明特征是模块化。我们有许多模块,其中一些从数据库中的3个表开始,最多30个表。大多数模块由业务和Web项目组成。业务项目保留业务和持久性逻辑,而Web保留表示逻辑。
从逻辑上讲,它分为三层:业务,持久性和表示。
依赖关系:
表示取决于业务和持久性。
持久性取决于业务。
业务不依赖其他层。

大多数业务项目具有三种类型的接口(注意:不是GUI,它是程序化的Java接口层)。

  1. 演示文稿用作客户端的界面
  2. 其他模块作为模块的客户端时正在使用的接口。
  3. 可以用于模块管理目的的接口。

通常,1扩展为2。这样,很容易用另一种实现替换模块实现。这有助于我们采用不同的客户并更轻松地进行集成。一些客户只会购买某些模块,我们需要集成他们已经拥有的功能。由于接口和实现层是分开的,因此很容易为该特定客户端推出ad-hock模块实现,而不会影响从属模块。Spring Framework使注入不同的实现变得容易。

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


3

这是我从事的另一种Web体系结构:

一个主要要求是该应用程序应支持手机/其他设备。该应用程序还应该可扩展或灵活地适应技术选择的变化。

演示层:

  • JSP / JQuery(客户端MVC)
  • 本机Android
  • 本机iPhone
  • 移动网络(HTML5 / CSS3 /自适应设计)

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

商业服务层:

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

数据访问层:

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

资源层:

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

你可以找到下面这个架构的书更多的信息在这里


2

恕我直言,我们大多数人都有一个共同的分母。在后端,我们有某种形式的IOC / DI容器和一个持久性框架。我个人使用Guice和Mybatis。不同之处在于我们如何实现视图/ UI /表示层。这里有2个主要选项(可能更多)。基于动作(将URL映射到控制器)和基于组件。当前正在使用基于组件的表示层(使用检票口)。它完美地模仿了桌面环境,在这里我使用组件和事件而不是URL和控制器。当前正在寻找我为什么要迁移到这种URL控制器类型的体系结构的原因(这就是我最终在此页面上看到的)。为什么大肆宣传RESTful和无状态架构。

简短地回答这个问题:我在Guice IOC容器的顶部使用面向组件的框架编写有状态的Web应用程序,并使用Mybatis将数据放入关系数据库中。


1

有点不同,在这里我将要求使用更多的模块化Java体系结构。我们有:

  1. Spring WS / Rest / JSP前端
  2. 用于业务服务逻辑的Spring MVC,包含表示层逻辑以及Spring事务
  3. 组件服务通信接口,由业务服务通过EJB查找。EJB设置了自己的事务边界,这些边界可以加入Spring事务。
  4. 组件服务实现,再次是Spring组件
  5. 集成层,用于数据库集成的MyBatis,用于Web服务集成的Spring WS,用于其他服务的其他集成技术
  6. 大型机,数据库,其他服务器上的其他服务...

除上述内容外,我们还有共享库模块,这是所有服务的通用功能提供程序。

使用不同的层可以使我们完全解耦,并实现所需的模块化。我们还能够充分利用Java EE和Spring的功能。例如,如果需要,没有什么可以阻止我们将JSF用于前端。

与OP的示例体系结构相比,我认为这可以描述为具有四个主要层,而不是三个主要层,尽管有所不同。


0

我已经在使用那种严格的经理模式的项目中工作。从历史上看,我是僵化体系的坚定拥护者,在这里,所有东西都放进了一个整齐的盒子。随着我事业的发展,我发现很多情况下都被迫这样做。我相信对应用程序设计采用更敏捷的思维方式会带来更好的产品。我的意思是,这将创建一组解决当前问题的类。而不是说“您为此建立了一个经理吗?”

我正在处理的当前项目是一个Web应用程序,结合了Spring MVC和RestEasy JSON / Ajax调用。在嵌入到我们控制器中的服务器端是一个明智的基于外观的数据层,具有JPA / Hibernate,用于直接数据库访问,某些EJB访问和一些基于SOAP的Web服务调用。将所有这些结合在一起是一些自定义的Java控制器代码,这些代码确定要序列化为JSON并返回到客户端的内容。

我们几乎没有时间来尝试创建一些统一的模式,而是选择采用Unix设计哲学的“更糟,更好”的想法。由于它比在某些严格的设计要求下制造东西要好得多,因此可以在生产线外进行着色并明智地构建东西。


0

Web应用程序体系结构中的组件包括:

1:浏览器:客户端交互

        HTML
        JavaScript
        Stylesheet

2:网际网路

3:网络服务器

        CSS
        Image
        Pages(Java render )

4:应用服务器

        App Webapp (Java interaction)
        Others WebApps

5:数据库服务器

        Oracle, SQL, MySQL

6:数据

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.