Java企业版101

有很多创建软件的方法。 实际上,甚至还有很多创建方法好 software. When it comes to application server development, one of them has stood the test of time, and for 好 reason: Java Enterprise Edition.

Java EE不仅仅是软件库。 它也是一种体系结构和哲学。 JEE不适合胆小的人; 如果您要构建一个废弃的原型,那您走错了路。 但是,如果您开始阅读可以承载大型企业并支持大规模应用程序的体系结构,那么您就是对的。 JEE是软件开发的重炮。 而且真是太棒了。

在本文中,我们将探讨JEE的体系结构方面。 有关实现的文章将很快发布。

一点说明。 当我在本文中谈论Java Enterprise时,我并不是在专门讨论库,而是在架构和哲学上。 官方Java EE库只是实现此堆栈的一种方法。

The JEE Stack

这样您就可以进行一些认真的软件开发了吗? 抛开所有无类型的语言,精美的脚本,炒作驱动的开发和时髦技术,让我们变得严肃起来,编写可在未来20多年运行的软件。 简而言之,这是Java EE体系结构:

Java企业版101

好吧,理所当然,你需要一个大简而言之。 让我们从一些初步的观察开始:

  • 与外界的每一次交流都是严格的请求-响应基于。传入请求通过多个层数在到达您的应用程序代码之前。 每层可以垃圾,重新导向要么改变 the request。 The motivation behind these 层数 is 关注点分离。Many of the 层数 are 已经实施 and you just need to make use of them。JEE就是要让开发人员只专注于业务功能。 99% of everything else has been taken care of for you。

Application Containers

When a request reaches our server machine over the network, it is first passed to the operating system. The OS will determine to which application to forward the request, based on the port it has been sent to. In this case, the application is the Java Virtual Machine. The JVM internally runs an application container (such as Apache Tomcat or Glassfish). An application container implements the Java Servlet API. An application container has several responsibilities:

  • 它管理一个或多个应用程序,这些应用程序作为小服务程序. In practice, most cotainers only hold a single servlet, but in theory one Tomcat can hold arbitrarily many 小服务程序.它提供了Servlet API的实现。 这允许所包含的应用程序与容器对话。 此功能最突出的用途是建立一个过滤链(稍后会详细介绍)。它提供了与服务操作系统的API。 这样,容器中运行的应用程序可以作为OS级服务启动,终止和重新启动。 因此,即使Java是多平台的,许多应用程序容器仍包含特定于平台的代码(因此所包含的应用程序仍与平台无关)。它将基于以下内容将传入请求重定向到正确的应用程序:路径映射。 看到一个注册的servlet包含静态内容(绑定到/静态的)和一个用于应用程序服务器的动态API(绑定到/ api)。它管理请求的线程池,并将每个请求绑定到一个线程。 由于线程持有请求上下文,不建议在JEE环境中手动启动新线程(除非您知道究竟 what you are doing)。

传统上,Java ËË应用程序是通过称为“战争文件(用于w ^eb增强现实细香葱)或Ë增强现实文件(用于Ë企业增强现实chive). The internal file structure of these archives is standardized. The application containers extract the contained files on startup and launch the contained servlet(s). w ^hile doing so, the container binds your servlet to the specified port (either specified in code or a configuration file).

The JEE Framework

通常,在使用JEE体系结构时,您不会从头开始实现所有功能。 从一个JEE应用程序到下一个JEE应用程序,许多任务是完全相同的,因此使用合适的框架非常有意义。 主要是有实际的JEE参考实现和Spring框架。 关于“香草” JEE,我不能说太多,因为到目前为止,我仅使用Spring框架。 我们将在下一篇文章中更详细地讨论它。

The Filter Chain

每个传入的请求在提交给您的应用程序之前,必须通过一系列所谓的Servlet过滤器,形成一个过滤链. Once a request passes the first filter, the second filter kicks in, and so on. Each filter has the option to block a request. Application containers allow to customize the 过滤链 via the Servlet API. The JEE framework implementations use the 过滤链 for many tasks, including session management and security. Filters can also have side-effects; if there is a task you want to perform per request, you will often see the implementation in the form of a servlet filter. Also, if you need to bind some information to the request itself, servlet filters are a common place to do so.

The Presentation Layer

表示层是您的实际应用程序代码首次满足传入请求的地方。 该请求已通过Servlet过滤器链,因此已建立用户会话并准备就绪,并且所有身份验证都已得到处理。 在JEE的早期,表示层是发生服务器端HTML页面的地方。 如今,表示层由一组REST控制器组成,这些控制器提供了构成REST API的各种端点。 如果您面对的是较旧的应用程序,则在表示层中还将遇到XML Web服务。 在表示层中要做的一件事是用户输入的服务器端验证和常规请求验证。 与永远不要在GUI代码中编写SQL查询(表示层)的方式相同禁止尝试直接访问数据库。 表示层中的类仅允许与另一个表示层类,服务层类或由服务层返回的数据模型的元素通信。

The Service Layer

服务层是您实际的应用程序代码所在的位置。 这是将业务规则纳入代码的地方。 服务层是您在数据模型中移动数据,创建新元素,删除旧元素等的地方。根据您的用例,服务层可能小到“将此调用转发到存储库层”,或者 极其复杂的过程。 服务层中的类只能与其他服务或存储库层中的类通信。

The Repository Layer

这是代码中的最后一层,可在数据到达数据库之前对其进行修改。 这一层的主要元素是储存库(也称为数据访问对象, 要么DAO * s)。 这些类仅提供了许多方法,可让您* persist,加载,删除和询问 your data in the database. What is important here is that you must never let any specifics of your data store escape the repository layer - its very purpose is to make sure that you can exchange the data store with a different one (potentially even an SQL database with a NoSQL store!). Internally,your repository methods will contain the actual 询问 statements. If you are working with a standard JEE stack,then you will have a Java持久性API (JPA) Provider such as Hibernate in place. JPA allows you to convert your domain model to SQL tables和back with 相对的 ease. It still has a lot of pitfalls和would be deserving of its own article. As you probably already guessed,the repository layer classes do not call any other classes outside of their own layer,except for JPA classes.

The Data Model

数据模型代表您的数据域。 这是将由全部三层您的应用程序。 因此关键 that the 域 model classes have 没有 references to any other classes, except for classes that reside within the 域 model themselves. In contrast to the presentation-, service-和persistence-layer classes, the 域 model是有状态的。 通常,您将不 want to have a lot of logic in the 域 model; it mostly exists to hold your data和provide a clean API, the actual complex modifications are done in the business layer. The 域 model, while 不 explicitly required in JEE, almost always follows the Java Bean pattern. Proper getters和setters are 不 negotiable here if you want to make use of standard frameworks for easily handling your 域 model, such as Bean Validation和JPA (more on that later). A 域 model element是your typical POJO - private fields, a constructor,和getters和setters. Usually, frameworks like JPA, Jackson和JAXB will in addition force you to give each class a default constructor, because these classes need to be instantiable via Java reflection. In contrast to almost all other classes in the JEE architecture, having a clean implementation of 等于()和hashCode()是关键 for 域 model POJOs. Usually, each 域 model element has a unique ID for this purpose, which also coincides with its ID in the database tables.

Threads in JEE

Java企业版101

一种请求总是绑定到线在JEE中,由应用容器实例化和管理(通常在线程池中)。 这意味着JEE服务器应用程序总是固有地并发,您无法避免这种情况。 众所周知,正确处理并发是硬. Thankfully, the JEE architecture has you covered when it comes to concurrency. If you look at the picture above, you see four users working with the application in parallel, each being represented by a 请求/response bound to a 线. There is one particular detail worth noting: the 线s 永不相交。 该应用程序不执行任何同步,而是将其留给真正擅长于此的组件:数据库。

这怎么可能? 我们如何在不考虑多线程的情况下将所有这些层置于数据库之上? 当并发成为问题时,请回想一下:当多个线程访问同一数据时。 您想不惜一切代价避免在JEE应用程序中发生这种情况(存在例外,例如应用程序级缓存)。 为了做到这一点,属于资料库层和服务层是无状态的在JEE中。 它们没有保持可变状态的私有或公共字段。 那么数据呢? 数据已加载每个用户和每个请求. When a request arrives at the 服务层 (the presentation layer is a bit of an exception here) then a new database transaction is opened for exclusive use by this user. The services then gather the requested data and/or perform the requested modifications, all inside this single transaction. Before the result is passed to the presentation layer, the transaction is committed和closed.

该体系结构具有两个主要优点:

  • 服务器是无状态的,这是一个不错的属性,例如 用于检测。 它有助于保持业务逻辑非常简单,并且可以使用功能更强的编程风格很好地工作。并发修改曾经遇到的唯一地方是在数据库中,但是它们是专门为处理该问题而设计的。

当然,代价是每个线程都建立自己的(部分)数据模型视图。 因此,如果两个用户请求相同的数据,它将被两次保存在内存中。

Closing Words

关于JEE,还有更多要说的。 我经常感到,仅仅是因为它被误解了,就引起了许多不当的批评。 它可以与现代编程风格和语言完美结合,并有助于构建非常稳定的应用程序。 在某种程度上,JEE与其说的是什么不一样提供作为程序员,对您来说却是保护您来自(并发问题,数​​据完整性问题...)。 在这方面,JEE架构是防御性编程的主要示例-一切都是安全第一。 该体系结构已被证明非常适合大型项目和团队。

在下一篇文章中,我们将通过一个具体示例仔细研究此架构的实际实现-这将需要很多时间减我们这方面的代码来实现所有这些比您想象的要好。

from: https://dev.to//martinhaeusler/java-enterprise-101-3djl