确保高效发展进程的建议java
好久之前,J2EE,特别是应用程序服务器被认为过于臃肿和“重量级”。对于开发人员来讲,使用此技术开发应用程序会很是繁琐且使人沮丧。可是,因为 J2EE 框架的名称已更改成Java EE,所以该假设再也不适用。 Java EE 与其余企业框架相比区别在哪以及框架轻量级的标准是什么?git
在选择技术时,须要考虑的最重要方面之一是开发人员在开发过程当中的生产力。工程师应该花费尽量多的时间来实现用例和创收功能,由于这将使公司朝着目标前进。github
所选择的技术和方法应该最大限度地缩短开发人员的时间。具体哪些时间呢:等待构建,测试和部署; 配置应用; 实施与业务用例无关的管道; 并配置构建环境和外部依赖项。 可是大多数可用技术都没有这样作。apache
与其余框架相比,Java EE 的最大优点之一是使用的API的标准化。标准听起来可能很无聊并且不够创新 - 从本质上讲,这是真的,由于Java规范请求(JSR)已经成为行业内过去已通过充分证实的结果。 但使用这些标准有几个优势。json
Java EE中的特定API - 例如上下文和依赖注入(CDI),JAX-RS,JSON 处理(JSR 353)和 Bean验证 - 能够很好地协同工做,而且能够无缝地相互组合。 最重要的是,CDI 被用做应用程序组件之间的“粘合剂”。 该规范包含诸如“若是容器支持规范 A 和 B,那么 A 必须与 B 无缝集成并良好地工做。”api
例如,JAX-RS 支持 JSONP 类型,例如JsonObject
用做请求或响应实体,它支持调用Bean 校验功能 - 若是验证失败,则包括正确的HTTP状态代码(参见清单1)。浏览器
@Path("duke")
public class DukeResource {
@GET
public JsonObject getDuke() {
return Json.createObjectBuilder().add("name", "Duke").build();
}
@POST
public void create(@Valid @NotPlayedYet Game game) {
// game object has been validated at this point
}
}复制代码
清单1. JAX-RS的JSONP和Bean Validation集成服务器
使用 JSONP 类型意味着内容类型将是 application / json
,而且若是验证失败,将发送HTTP状态代码 400 Bad Request
。 这无需编写任何配置代码就能使一切都完成。架构
另外一个例子是 CDI 使开发人员可以经过 @Inject
将任何 bean 和用户定义的对象注入 Java EE托管组件。 请参阅清单2,了解一个 bean 验证 Validator
,它直接使用另外一个 CDI 托管bean。oracle
public class GameNotPlayedValidator implements ConstraintValidator<NotPlayedYet, Game> {
@Inject
GameHistory history;
public void initialize(NotPlayedYet constraint) {
// no initialization needed
}
public boolean isValid(Game game, ConstraintValidatorContext context) {
return !history.exists(game);
}
}复制代码
清单2. bean 验证的 CDI 集成
集成是规范的一个主要方面,能够提供直接的开发人员体验。开发人员能够依赖应用程序服务器进行集成和配置工做,从而能够专一于应用程序的业务逻辑。
因为 Java EE 的配置约定驱动方法,大多数实际应用程序不须要大量配置。 繁琐的 XML 描述符的日子结束了。 对于简单的 Java EE 应用程序,您不须要单个 XML 文件。
因为声明性注释,一个简单的带注释的普通旧 Java 对象(POJO)处理 HTTP 请求(@Path
),或分别做为 Enterprise JavaBeans(EJB)bean(@ Stateless
) - 包括事务,监视或拦截器。过去,这些方法已在各类框架中获得很好的证实,并已在 Java EE 中进行了标准化。
若是须要,XML 描述符仍可用于部署时配置,可是配置约定有助于最大限度地提升开发人员的工做效率。
少数实际企业项目在部署工件中没有任何额外依赖项的状况下工做。 但这些依赖关系的理由主要是由技术驱动 - 例如包括日志记录或实体映射框架或 Apache Commons 或 Google Guava 等经常使用库 - 而不是用例。
Java EE 7 - 尤为是与 Java 8 一块儿使用时 - 具备足够的功能来覆盖大多数用例而没有任何其余依赖性。开箱即用的内容大部分均可以用最少许的代码来实现,例如,经过 CDI 提供商的可注入配置,经过拦截器的断路器(查看 Adam Bien 的开源库),或经过复杂的收集操做 Java 8 lambda 表达式和流。
固然,你能够争辩说不要在这里从新发明轮子。 但实际上,为了节省一些自编写的代码行,将兆字节的外部依赖项包含在部署工件中并无多大意义。
经验代表,最大的问题不是直接引入的依赖,而是传递的依赖。传递的依赖常常与应用程序服务器上已有的库版本冲突,并致使具备挑战性的冲突。在一天的工做时间内,开发人员要花费更多时间来管理这些冲突,而不是聚焦在将小功能实现到项目中所需的时间。这主要适用于具备技术驱动而非用例驱动的依赖关系的状况。
有关简单的 Java EE 7 项目Maven项目对象模型(POM)的文件启发,请参阅清单 3,该文档受Adam Bien的启发 Java EE 7 Essentials Archetype.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sebastian-daschner</groupId>
<artifactId>game-of-duke</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>game-of-duke</finalName>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>复制代码
清单3. Java EE 7 Maven POM 文件
固然,有时应用程序确实须要集成对于实现软件目标相当重要的库。可是,这些依赖关系须要经过业务需求来证实。通常来讲,它颇有意义,能够节省时间和精力来最小化外部生产库。
对于测试依赖关系,这是一个不一样的故事,由于库,例如JUnit,Mockito或者在某些状况下,Arquillian - 是相当重要的。 但一样,关注测试依赖项列表也是有意义的。
因为应用程序服务器知道Java EE API,所以该API没必要包含在部署 artifact 中。 只包含业务逻辑 - 只需最少的胶水代码和交叉关注点。
所以,这些千字节大小的工件可使构建时间很是短,由于构建过程不须要复制不少东西。这能够在每一个构建上产生几秒钟的差别。 若是总结开发人员和持续集成(CI)服务器所花费的全部额外时间,那就会产生很大的不一样。项目建设的频率越高 - 对于持续交付(CD)情景尤为如此 - 影响越大。
除了较短的构建时间外,小型部署 artifacts 还可确保较短的发布和部署时间。 因为实现已经包含在运行时中,因此在全部状况下,移动部件花费的时间都是最小的。
这正是Java EE成为Docker等容器技术的完美框架的缘由。Docker 镜像基于图层,构建图像时,基本图像已包含操做系统,Java运行时和应用程序。所以,在每一个构建中添加的惟一内容是部署工件的最后一个千字节薄层。与胖WAR或独立JAR方法相比,这节省了时间和存储 - 不只在每一个构建上,并且在图像版本化或发布版本时 。
不管在哪一个阶段,拥有精简的部署 artifacts 均可以实现很是快速和高效的部署管道。
J2EE 应用程序服务器是重量级软件在启动和部署时间,安装大小和资源占用空间方面的体现。 可是在 Java EE 的新世界中,这已再也不适用。
全部现代Java EE 7应用程序服务器(如WildFly,Payara,WebSphere Liberty,Profile和TomEE)均可在几秒钟内启动和部署。因为内部,全面的模块化,他们只能加载所需的组件并尽快部署精简的应用程序 artifacts。
如今的安装尺寸和占地面积很是合理。 应用程序服务器不会消耗比简单的 servlet 容器更多的东西,但它具备完整的 Java EE 功能。 有趣的是,如今运行的浏览器实例消耗更多内存。
话虽如此,每一个服务器只部署一个应用程序是可能的,也能够是合理的 - 不管是在容器中仍是在内部。 经过“每一个容器每一个应用程序服务器一个应用程序”方法,您能够为现代微服务架构提供高效且灵活的解决方案。
在打包过程当中,不该该继续使用EAR文件了。将整个应用程序部署在独立的专门的服务器上,要求咱们在那个环境中必须能够访问全部的组件方法,这样作能够节省更多的构建和部署时间。除此以外,这还避免了EAR文件倾向于致使的类加载层次结构问题。
在大多数云和微服务部署中,使用独立的JAR包。 它们包含应用程序和运行时实现。 在Java EE领域,这种方法可使用特定于供应商的工具链来实现,例如 WildFly Swarm,Payara Micro 或TomEE Embedded。
可是,因为上述缘由,我强烈建议尽量将业务逻辑与运行时分开。 这意味着将应用程序打包在仅包含应用程序代码的WAR文件中。
在我看来,若是因为公司“政治”问题而不是技术缘由而没法控制安装或操做流程,则独立 JAR 文件是一种有用的解决方法。 而后运送部署工件中所需的全部内容而且只须要 JRE 时能够解决至关多的非技术问题。
企业项目最有效的解决方案之一以下:
“重量级 Java EE”的日子确定结束了。 Java EE 中包含的 API 提供了高效且愉快的开发人员体验以及标准内的无缝集成。 特别是,将应用程序代码与运行时分离的方法可实现快速,高效的开发过程。
经过由多个供应商发起的新MicroProfile计划,未来可能会进一步缩小Java EE所需的组件。
原文:https://community.oracle.com/docs/DOC-1008823
做者:Sebastian Daschner
译者:[KeepGoingPawn](https://blog.csdn.net/hengji666
------
9月福利,关注公众号后台回复:004,领取8月翻译集锦!往期福利回复:001,002, 003便可领取!