Describe the architecture you use for Java web applications?
让我们共享基于Java的Web应用程序体系结构!
Web应用程序有很多不同的体系结构,它们将用Java来实现。这个问题的答案可以作为各种Web应用程序设计及其优缺点的库。虽然我认识到答案是主观的,但让我们尽量客观,并激励我们列出的利弊。
使用您喜欢的详细程度来描述您的体系结构。为了让你的答案具有任何价值,你至少需要描述一下你所描述的体系结构中使用的主要技术和思想。最后,但并非最不重要的是,我们什么时候应该使用您的体系结构?
我将开始…
体系结构概述我们使用基于Sun的开放式标准的三层架构,如JavaEE、Java持久化API、Servlet和Java服务器页面。
- 坚持不懈
- 业务
- 演示
层之间可能的通信流表示为:
1 | Persistence <-> Business <-> Presentation |
例如,这意味着表示层从不调用或执行持久性操作,它总是通过业务层来实现。此体系结构旨在满足高可用性Web应用程序的需求。
坚持不懈执行创建、读取、更新和删除(CRUD)持久性操作。在我们的例子中,我们使用的是Java持久化API(JavaPrimultAPI),我们目前使用Hibernate作为持久性提供程序并使用它的EntyMealm管理器。
该层分为多个类,其中每个类处理特定类型的实体(即与购物车相关的实体可能由单个持久性类处理),并且由一个且只有一个管理器使用。
此外,该层还存储JPA实体,如
所有与Web应用程序功能相关的逻辑都位于这一层。此功能可以为希望使用其信用卡在线支付产品的客户启动转账。它也可以创建一个新用户,删除一个用户,或者在一个基于网络的游戏中计算一场战斗的结果。
该层分为多个类,每个类都用
当
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ... 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教程如何解释Enterprise JavaBeans(EJB)所需的事务属性:
If the client is running within a
transaction and invokes the enterprise
bean’s method, the method executes
within the client’s transaction. If
the client is not associated with a
transaction, the container starts a
new transaction before running the
method.The Required attribute is the implicit
transaction attribute for all
enterprise bean methods running with
container-managed transaction
demarcation. You typically do not set
the Required attribute unless you need
to override another transaction
attribute. Because transaction
attributes are declarative, you can
easily change them later.
演示
我们的演示层负责…演示!它负责用户界面,并通过构建HTML页面和通过GET和POST请求接收用户输入向用户显示信息。我们目前使用旧的servlet的+ Java服务器页面(JSP)组合。
层调用业务层管理器中的方法来执行用户请求的操作,并接收要在网页中显示的信息。有时,从业务层接收到的信息不像
- 在这个层中拥有与特定的持久性方法相关的所有东西只意味着我们可以从使用JPA转换到其他东西,而不必在业务层中重新编写任何东西。
- 我们很容易将表示层换成其他层,如果找到更好的层,我们很可能会换成其他层。
- 让EJB容器管理事务边界很好。
- 使用servlet's+jpa很容易(首先),而且这些技术在许多服务器中被广泛使用和实现。
- 使用JavaEE可以使我们更容易创建具有负载平衡和故障转移的高可用性系统。这两个我们都觉得我们必须拥有。
欺骗
- 使用JPA,您可以使用JPA实体类上的
@NamedQuery 注释将常用查询存储为命名查询。如果您在持久性类中尽可能多地与持久性相关,就像在我们的体系结构中一样,这将分散到好的,我做一个(较短的)一个:
- 前端:挂毯(旧项目3个,新项目5个)
- 业务层:春季
- 道氏:伊巴蒂斯
- 数据库:Oracle
我们使用sping事务支持,在进入服务层后启动事务,并向下传播到DAO调用。服务层具有最多的业务模型知识,DAO执行相对简单的CRUD工作。
出于性能方面的考虑,一些更复杂的查询内容由后端中更复杂的查询处理。
在我们的示例中使用Spring的好处是,我们可以拥有依赖于国家/语言的实例,这些实例位于Spring代理类后面。根据会话中的用户,进行呼叫时使用正确的国家/语言实现。
事务管理几乎是透明的,在运行时异常时回滚。我们尽可能使用未检查的异常。我们曾经做过检查异常,但是随着Spring的引入,我看到了未检查异常的好处,只有在您能够处理异常时才能处理异常。它避免了大量的样板文件"捕获/再抛出"或"抛出"的东西。
对不起,比你的帖子短,希望你能找到这个有趣的…
当今基于Java的理想的Web开发技术。
网络层:html+css+ajax+jquery
RESTful Web控制器/操作/请求处理层:游戏框架
业务逻辑/服务层:尽可能使用纯Java代码。我们可以在这里进行Web服务的融合。
XML/JSON数据转换层:xmltool(搜索谷歌代码)、jsoup、google gson、xstream、joox(搜索谷歌代码)
持久层:CRUD:JPA或Sienaproject或QueryDSL/复杂查询:jooq、querydsl
这是我的5美分
演示Android,angular.js网络客户端,OAuthv2
美国石油学会REST、Jersey(JAX-RS)、Jackson(JSON de-/serialisation)、DTO对象(不同于业务逻辑模型)
业务逻辑用于DI和事件处理的弹簧。模型对象的DDD ISH方法。工作模块中的sqs可以卸载运行时间较长的作业。
道使用SpringJDBC模板存储实体的存储库模型。redis(jedis)用于排行榜,使用有序列表。令牌存储的memcache。
数据库mysql、memcached、redis
我们在项目中遵循的是:
前端技术
- 角晶状体
- HTML5
- CSS3
- JavaScript
- 引导3
美国石油学会
- 休息
- 泽西(JAX-RS)
- 放心
- 弹簧靴
- 杰克逊
- 春季安全
弹簧数据
春季数据MongoDB
- 蒙哥大
- 雷迪斯
- 演示文稿用作客户端的接口
- 当其他模块是模块的客户端时,它们使用的接口。
- 可用于模块管理目的的接口。
- jsp/jquery(客户端MVC)
- 本地Android
- 原生iPhone
移动网络(HTML5/CSS3/响应式设计)
弹簧架控制器(可改为JAX-RS)
- 弹簧WS/REST/JSP前端
- 用于业务服务逻辑的SpringMVC,包含表示层逻辑和Spring事务
- 组件服务通信接口,由业务服务通过EJB查找。EJB设置了自己的事务边界,这些边界能够连接Spring事务。
- 组件服务实现,同样是Spring组件
- 集成层,用于数据库集成的MyBatis,用于Web服务集成的Spring WS,用于其他服务的其他集成技术
- 主机、数据库、其他服务器上的其他服务…
业务逻辑
数据库
服务器(用于缓存)
我们仍在使用通常的Struts Spring Hibernate堆栈。
对于未来的应用程序,我们正在研究SpringWebFlow+SpringMVC+Hibernate或Spring+Hibernate+Web服务,前端灵活。
我们体系结构的一个显著特征是模块化。我们有许多模块,有些模块从数据库中的3到最多30个表开始。大多数模块由业务和Web项目组成。业务项目持有业务和持久性逻辑,而Web持有表示逻辑。
在逻辑层面上,有三层:业务层、持久性层和表示层。
相关性:
演示取决于业务和持久性。
坚持取决于业务。
业务不依赖于其他层。
大多数业务项目有三种类型的接口(注意:不是GUI,它是一个程序化的Java接口层)。
通常,1延伸2。这样,很容易用另一个实现替换模块的一个实现。这有助于我们适应不同的客户,更容易集成。有些客户机只购买某些模块,我们需要集成他们已经拥有的功能。由于接口和实现层是分离的,因此很容易为特定的客户机执行ad hock模块,而不影响依赖模块。Spring框架使得注入不同的实现变得容易。
我们的业务层基于Pojos。我观察到的一个趋势是这些pojos类似于dto。我们患有贫血域模型。我不太清楚为什么会发生这种情况,但这可能是由于我们许多模块的问题域的简单性,大部分工作都是CRUD,或者是因为开发人员更喜欢将逻辑放在其他地方。
下面是我所研究的另一个Web体系结构:
One major requirement was the application should support mobiles/other
devices. The application should also be extensible or flexible to
changes in technology choices.
演示层:
业务服务层:
Spring@Service(可以更改为无状态EJB)
数据访问层:
spring@repository(可以更改为无状态EJB)
资源层:
休眠(JPA)实体(可以更改为任何ORM)
你可以在这本遵循这种架构的书中找到更多的信息。
imho,我们大多数人都有共同点。至少在后端,我们有某种形式的IOC/DI容器和持久性框架。我个人用Guice和Mybatis来做这个。不同之处在于我们如何实现视图/ui/表示层。这里有两个主要选项(可能更多)。基于操作(URL映射到控制器)和基于组件。目前正在使用基于组件的表示层(使用Wicket)。它完美地模拟了一个桌面环境,我使用组件和事件,而不是URL和控制器。我目前正在寻找一个原因,为什么我应该迁移到这种URL控制器类型的体系结构(这就是我在这个页面上的结束方式)。为什么要大肆宣传RESTful和无状态架构。
简而言之,要回答这个问题:我使用guice ioc容器之上的面向组件的框架编写有状态的Web应用程序,并使用mybatis将数据放入关系数据库。
有点不同,我会在这里要求更多的模块化Java体系结构。我们有:
除上述之外,我们还有共享库模块,它是所有服务的通用功能提供者。
使用不同的层可以实现完全的解耦和所需的模块化。我们还能够充分利用JavaEE和Spring的能力。例如,如果需要的话,没有什么可以阻止我们使用JSF作为前端。
与OP的示例架构相比,我认为这可以描述为有四个主要层而不是三个,尽管有点扭曲。
Web应用程序体系结构中的组件包括:
1:浏览器:客户端交互
1 2 3 |
2:互联网
3:Web服务器
4:应用服务器
1 2 | App Webapp (Java interaction) Others WebApps |
5:数据库服务器
1 | Oracle, SQL, MySQL |
6:数据
我曾经在使用那种死板的管理者模式的项目上工作过。从历史上看,我是严格等级制度的拥护者,所有东西都放在一个整洁的盒子里。随着我事业的发展,我发现在很多情况下都是被迫的。我相信在应用程序设计上采用更灵活的思维方式会得到更好的产品。我的意思是创建一组类来解决手头的问题。而不是说"你为这个和那个建立了经理吗?"
我正在研究的当前项目是一个结合了SpringMVC和RestEasyJSON/Ajax调用的Web应用程序。在我们的控制器中嵌入的服务器端是一个基于外观的数据层,它具有JPA/Hibernate直接访问数据库、一些EJB访问和一些基于SOAP的Web服务调用。将所有这些绑定在一起是一些自定义Java控制器代码,它决定将JSON序列化并返回到客户端。
我们几乎没有花时间尝试创建一些统一的模式,而是选择采用Unix设计理念中的"越坏越好"的概念。因为它是更好的颜色以外的线和建立一些明智的东西,比它是建立一些坚持一系列严格的设计任务。