描述您用于 Java Web 应用程序的架构? [英] Describe the architecture you use for Java web applications?

查看:21
本文介绍了描述您用于 Java Web 应用程序的架构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

要使用 Java 实现的 Web 应用程序有许多不同的架构.这个问题的答案可以作为各种 Web 应用程序设计及其优缺点的库.虽然我意识到答案将是主观的,但让我们尽量保持客观并激发我们列出的利弊.

There are lots of different architectures for web applications which are to be implemented using Java. The answers to this question may serve as a library of various web application designs with their pros and cons. While I realize that the answers will be subjective, let's try to be as objective as we can and motivate the pros and cons we list.

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

Use the detail level you prefer for describing your architecture. For your answer to be of any value you'll at least have to describe the major technologies and ideas used in the architecture you describe. And last but not least, when should we use your architecture?

我会开始...

我们使用基于 Sun 开放标准的 3 层架构,如 Java EE、Java Persistence API、Servlet 和 Java Server Pages.

We use a 3-tier architecture based on open standards from Sun like Java EE, Java Persistence API, Servlet and Java Server Pages.

  • 坚持
  • 业务
  • 介绍

层之间可能的通信流表示为:

The possible communication flows between the layers are represented by:

Persistence <-> Business <-> Presentation

例如,表示层从不调用或执行持久性操作,它总是通过业务层来完成.此架构旨在满足高可用性 Web 应用程序的需求.

Which for example means that the presentation layer never calls or performs persistence operations, it always does it through the business layer. This architecture is meant to fulfill the demands of a high availability web application.

执行创建、读取、更新和删除(CRUD)持久性操作.在我们的例子中,我们使用 (Java Persistence API) JPA,我们目前使用 Hibernate 作为我们的持久性提供者并使用 它的 EntityManager.

Performs create, read, update and delete (CRUD) persistence operations. In our case we are using (Java Persistence API) JPA and we currently use Hibernate as our persistence provider and use its EntityManager.

这一层分为多个类,其中每个类处理某种类型的实体(即与购物车相关的实体可能由单个持久性类处理)并由一个使用并且只有一名经理.

This layer is divided into multiple classes, where each class deals with a certain type of entities (i.e. entities related to a shopping cart might get handled by a single persistence class) and is used by one and only one manager.

此外,该层还存储 JPA 实体,例如 AccountShoppingCart

In addition this layer also stores JPA entities which are things like Account, ShoppingCart etc.

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

All logic which is tied to the web application functionality is located in this layer. This functionality could be initiating a money transfer for a customer who wants to pay for a product on-line using her/his credit card. It could just as well be creating a new user, deleting a user or calculating the outcome of a battle in a web based game.

这一层分为多个类,每个类都用@Stateless注解成为无状态会话 Bean (SLSB).每个 SLSB 被称为一个 manager,例如,一个 manager 可以是一个被标注为 AccountManager 的类.

This layer is divided into multiple classes and each of these classes is annotated with @Stateless to become a Stateless Session Bean (SLSB). Each SLSB is called a manager and for instance a manager could be a class annotated as mentioned called AccountManager.

AccountManager 需要执行CRUD 操作时,它会适当调用AccountManagerPersistence 的实例,该实例是持久层中的一个类.AccountManager 中两种方法的粗略草图可能是:

When AccountManager needs to perform CRUD operations it makes the appropriate calls to an instance of AccountManagerPersistence, which is a class in the persistence layer. A rough sketch of two methods in AccountManager could be:

...
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 方法时启动一个事务,并在退出该方法之前立即提交(或回滚)它.这是一个约定优于配置的例子,但除了默认的必需项之外,我们还不需要任何东西.

We use container manager transactions so we don't have to do transaction demarcation our self's. What basically happens under the hood is we initiate a transaction when entering the SLSB method and commit it (or rollback it) immediately before exiting the method. It's an example of convention over configuration, but we haven't had a need for anything but the default, Required, yet.

以下是 Sun 的 Java EE 5 教程如何解释 Enterprise JavaBeans (EJB's) 所需的事务属性:

Here is how The Java EE 5 Tutorial from Sun explains the Required transaction attribute for Enterprise JavaBeans (EJB's):

如果客户端在一个交易和调用企业bean的方法,方法执行在客户的交易中.如果客户端没有关联事务,容器启动一个运行之前的新事务方法.

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.

Required 属性是隐式的所有人的交易属性运行的企业 bean 方法容器管理事务划界.您通常不设置除非你需要,Required 属性覆盖另一笔交易属性.因为交易属性是声明性的,你可以以后轻松更改它们.

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) 组合.

Presentation

Our presentation layer is in charge of... presentation! It's responsible for the user interface and shows information to the user by building HTML pages and receiving user input through GET and POST requests. We are currently using the old Servlet's + Java Server Pages (JSP) combination.

该层调用业务层managers中的方法来执行用户请求的操作并接收信息显示在网页中.有时从业务层接收到的信息是 String's 和 integers 等不太复杂的类型,而在其他时候 JPA 实体.

The layer calls methods in managers of the business layer to perform operations requested by the user and to receive information to show in the web page. Sometimes the information received from the business layer are less complex types as String's and integers, and at other times JPA entities.

  • 在此层中拥有与执行持久性的特定方式相关的所有内容仅意味着我们可以从使用 JPA 转换为其他内容,而无需在业务层中重新编写任何内容.
  • 我们很容易将我们的表示层换成其他东西,如果我们找到更好的东西,我们很可能会这样做.
  • 让 EJB 容器管理事务边界很好.
  • 使用 Servlet 的 + JPA 很容易(一开始),而且这些技术在许多服务器中得到广泛使用和实现.
  • 使用 Java EE 应该可以让我们更轻松地创建具有 load 的高可用性系统平衡故障转移.这两者我们都觉得我们必须拥有.
  • Having everything related to a specific way of doing persistence in this layer only means we can swap from using JPA into something else, without having to re-write anything in the business layer.
  • 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.
  • Letting the EJB container manage transaction boundaries is nice.
  • Using Servlet's + JPA is easy (to begin with) and the technologies are widely used and implemented in lots of servers.
  • Using Java EE is supposed to make it easier for us to create a high availability system with load balancing and fail over. Both of which we feel that we must have.
  • 使用 JPA,您可以通过在 JPA 实体类上使用 @NamedQuery 注释将常用查询存储为命名查询.如果您在持久性类中尽可能多地与持久性相关,就像在我们的架构中一样,这将分散您可能会发现查询的位置,以包括 JPA 实体.将更难概览持久性操作,因此更难维护.
  • 我们将 JPA 实体作为持久层的一部分.但是AccountShoppingCart,它们真的不是业务对象吗?这样做是因为您必须接触这些类并将它们转换为 JPA 知道如何处理的实体.
  • JPA 实体也是我们的业务对象,其创建方式类似于数据传输对象 (DTO's),也称为值对象 (VO's).这会导致贫血域模型,因为业务对象除了访问器方法之外没有自己的逻辑.所有逻辑都由我们的业务层经理完成,这导致了更加程序化的编程风格.这不是一个好的面向对象设计,但也许这不是问题?(毕竟,面向对象并不是唯一产生结果的编程范式.)
  • 使用 EJB 和 Java EE 会带来一些复杂性.而且我们不能纯粹使用 Tomcat(添加 EJB 微容器不是纯粹 Tomcat).
  • 使用 Servlet 的 + JPA 存在很多问题.使用 Google 获取有关这些问题的更多信息.
  • 由于事务在退出业务层时关闭,因此我们无法从 JPA 实体加载任何信息,这些实体配置为在需要时从数据库加载(使用 fetch=FetchType.LAZY)从表示层内部.它会触发异常.在返回包含这些类型字段的实体之前,我们必须确保调用相关的 getter.另一种选择是使用 Java 持久性查询语言 (JPQL) 并执行 FETCH JOIN.但是,这两个选项都有些麻烦.
  • Using JPA you may store often used queries as named queries by using the @NamedQuery annotation on the JPA entity class. If you have as much as possible related to persistence in the persistence classes, as in our architecture, this will spread out the locations where you may find queries to include the JPA entities as well. It will be harder to overview persistence operations and thus harder to maintain.
  • We have JPA entities as part of our persistence layer. But Account and ShoppingCart, aren't they really business objects? It is done this way as you have to touch these classes and turn them into entities which JPA knows how to handle.
  • The JPA entities, which are also our business objects, are created like Data Transfer Objects (DTO's), also known as Value Objects (VO's). This results in an anemic domain model as the business objects have no logic of their own except accessor methods. All logic is done by our managers in the business layer, which results in a more procedural programming style. It's not good object oriented design, but maybe that's not a problem? (After all object orientation isn't the only programming paradigm which has delivered results.)
  • Using EJB and Java EE introduces a bit of complexity. And we can't use purely Tomcat (adding an EJB micro-container isn't purely Tomcat).
  • There are lots of issues with using Servlet's + JPA. Use Google for more information about these issues.
  • As the transactions are closed when exiting the business layer we can't load any information from JPA entities which is configured to be loaded from the database when it's needed (using fetch=FetchType.LAZY) from inside the presentation layer. It will trigger an exception. Before returning an entity containing these kinds of fields we have to be sure to call the relevant getter's. Another option is to use Java Persistence Query Language (JPQL) and do a FETCH JOIN. However both of these options are a little bit cumbersome.

推荐答案

好的,我会做一个(更短的):

Ok I'll do a (shorter) one:

  • 前端:Tapestry(3 个用于旧项目,5 个用于新项目)
  • 业务层:Spring
  • DAO 的:Ibatis
  • 数据库:Oracle
  • Frontend : Tapestry (3 for older projects, 5 for newer projects)
  • Business layer: Spring
  • DAO's : Ibatis
  • Database : Oracle

我们使用 Sping 事务支持,并在进入服务层时启动事务,向下传播到 DAO 调用.Service层有最多的业务模型知识,DAO做比较简单的CRUD工作.

We use Sping transaction support, and start transactions upon entering the service layer, propagating down to the DAO call's. The Service layer has the most bussines model knowledge, and the DAO's do relatively simple CRUD work.

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

Some more complicated query stuff is handled by more complicated queries in the backend for performance reasons.

在我们的案例中使用 Spring 的优点是我们可以拥有依赖于国家/语言的实例,这些实例位于 Spring Proxy 类之后.根据会话中的用户,拨打电话时使用正确的国家/地区/语言实现.

Advantages of using Spring in our case is that we can have country/language dependant instances, which are behind a Spring Proxy class. Based on the user in the session, the correct country/language implementation is used when doing a call.

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

Transaction management is nearly transparent, rollback on runtime exceptions. We use unchecked exceptions as much as possible. We used to do checked exceptions, but with the introduction of Spring I see the benefits of unchecked exceptions, only handling exceptions when you can. It avoids a lot of boilerplate "catch/rethrow" or "throws" stuff.

对不起,它比你的帖子短,希望你觉得这很有趣......

Sorry it's shorter than your post, hope you find this interesting...

这篇关于描述您用于 Java Web 应用程序的架构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆