Java EE8中的5大新特性


备受期待的Java Enterprise Edition 8发布版拥有两个令人兴奋的新API(JSON-Binding 1.0和Java EE Security 1.0),以及对当前API的改进(JAX-RS 2.1,Bean Validation 2.0,JSF 2.3,CDI 2.0,JSON-P 1.1,JPA 2.2和Servlet 4.0)。这是Oracle企业Java平台近四年来的第一个版本,它包含了数百个新特性,更新的功能和bug修复。

那么,最棒的新功能有哪些呢?我试图在这篇文章中回答这个非常主观的问题。

TL;DR的5大新功能

  1. 新的安全API:注释驱动的身份验证机制。全新的安全API包含三个优秀的新特性:身份存储抽象,新的安全上下文和新的注释驱动的身份验证机制web.xml文件声明已过时。最后一个就是我今天要讲的。
  2. JAX-RS 2.1:新的反应客户机。JAX-RS2.1中新的reactive client,它采用了reactive编程风格,并允许端点结果的组合。
  3. 新的JSON绑定API。新的JSON-binding API,它为JSON序列化和反序列化提供了一个本机Java EE解决方案。
  4. CDI 2.0:在Java SE中使用。CDI2.0中这个有趣的新特性允许在Java SE应用程序中引导CDI。
  5. Servlet 4.0:服务器推送。Servlet4.0中的服务器推送特性使Servlet规范与HTTP/2保持一致。

你可能对这本新书感兴趣Java EE 8: Only What's New只要9.95美元。它包含了Java EE8的所有添加,并提供了大量的代码示例。

你准备好了吗?所以我们开始吧。

1.新的安全API

Java EE8中添加的最重要的新特性可能是新的安全API。

这个新API的主要动机是简化,标准化和现代化跨容器和实现处理安全问题的方式。而且他们做得很棒。

  • 由于三个新的注释,web身份验证的配置已经现代化web.xml文件声明冗余。稍后会有更多关于这方面的内容。
  • 新的安全上下文API标准化了servlet和EJB容器执行身份验证的方式。
  • 新的标识存储抽象简化了标识存储的使用。

让我们来看看第一个添加。

注解驱动的认证机制

这个特性是关于配置web安全性的。中需要哪个传统的XML声明web.xml文件。

由于HttpAuthenticationMechanism接口,它表示HTTP身份验证,并附带三个内置的支持CDI的实现,每个实现都表示可以配置web安全性的三种方式之一。

它们是通过使用这些注释之一触发的。

@BasicAuthenticationMechanismDefinition
@FormAuthenticationMechanismDefinition
@CustomFormAuthenticationMechanismDefinition

它们复制了servlet容器中已经可用的经典HTTP基本身份验证,表单和自定义基于表单的身份验证的功能。

例如,要启用基本身份验证,只需添加BasicAuthenticationMechanismDefinition注释到servlet,仅此而已。

@BasicAuthenticationMechanismDefinition(realmName="${'user-realm'}")
@WebServlet("/user")
@DeclareRoles({ "admin", "user", "demo" })
@ServletSecurity(@HttpConstraint(rolesAllowed = "user"))
public class UserServlet extends HttpServlet { ... }

现在,您可以抛弃XML配置,使用这些新注释之一来驱动web安全性。

2.JAX-RS 2.1:新的反应客户机

让我们来看看JAX-RS2.1中的新的反应式客户机,以及它是如何拥抱反应式编程风格的。

反应式方法以数据流的思想为中心,具有通过流传播更改的执行模型。一个典型的例子是JAX-RS方法调用。当调用返回时,对方法调用的结果(可能是继续,完成或错误)执行下一个操作。

您可以将它看作是一个进程的异步管道数据,下一个进程作用于前一个进程的结果,然后将其进程的结果传递给链中的下一个进程。流的可组合性,这样你就可以将许多流组合并转换成一个结果。

的实例上的方法来启用反应特性rx()Invocation.Builder用于构造客户端实例。它的返回类型是CompletionStage 使用参数化的Response打字。这个CompletionStage接口是在Java8中引入的,并提出了一些有趣的可能性。

例如,在此代码段中,对不同的端点进行了两次调用,然后将结果组合在一起:

CompletionStage<Response> cs1 = ClientBuilder.newClient()
  .target(".../books/history")
  .request()
  .rx()
  .get();

CompletionStage<Response> cs2 = ClientBuilder.newClient()
  .target(".../books/geology")
  .request()
  .rx()
  .get();

cs1.thenCombine(cs2, (r1, r2) ->
  r1.readEntity(String.class) + r2.readEntity(String.class))
  .thenAccept(System.out::println);

3.新的JSON绑定API

现在,让我们进入下一个伟大的特性。新的JSON绑定API为JSON序列化和反序列化提供了原生Java EE解决方案。

以前,如果您想要序列化Java到JSON和从JSON反序列化Java,您将不得不依赖于第三方API,如Jackson或GSON。再也不是了。有了新的JSON绑定API,您就拥有了所有您可能想要的本机可用的特性。

从Java对象生成JSON文档再简单不过了。只需调用toJson()方法,并将要序列化的实例传递给它。

String bookJson = JsonbBuilder.create().toJson(book);

将JSON文档反序列化为Java对象也同样简单。只需将JSON文档和目标类传递给fromJson()方法,然后弹出Java对象。

Book book = JsonbBuilder.create().fromJson(bookJson, Book.class);

但这还不是全部。

行为定制

可以通过注释字段,JavaBeans方法和类来定制默认的序列化和反序列化行为。

例如,可以使用@JsonbNillable自定义空处理和@JsonbPropertyOrder用于自定义属性顺序的批注,该属性顺序是在类级别指定的。可以使用@JsonbNumberFormat()批注,并使用@JsonbProperty()注释。

@JsonbNillable
@JsonbPropertyOrder(PropertyOrderStrategy.REVERSE)
public class Booklet {

  @JsonbProperty("cost")
  @JsonbNumberFormat("#0.00")
  private Float price;

}

或者,您可以选择使用运行时配置生成器来处理自定义,JsonbConfig

JsonbConfig jsonbConfig = new JsonbConfig()
     .withPropertyNamingStrategy( PropertyNamingStrategy.LOWER_CASE_WITH_DASHES)
     .withNullValues(true)
     .withFormatting(true);

Jsonb jsonb = JsonbBuilder.create(jsonbConfig);

无论哪种方式,JSON绑定API都为Java对象的序列化和反序列化提供了广泛的功能。

4.CDI 2.0:在Java SE中使用

现在让我们进入下一个API。CDI 2.0 API。这个版本拥有许多新特性,其中一个更有趣的特性是在Java SE应用程序中引导CDI的能力。

要在Java SE中使用CDI,必须显式引导CDI容器。这是通过调用静态方法来实现的newInstance()在。。。上SeContainerInitializer抽象类。它返回 SeContainer实例,它是CDI运行时的句柄,使用它可以执行CDI解析,如此代码段所示。它可以访问BeanManager,BeanManager是CDI的核心入口点。

SeContainer seContainer =
       SeContainerInitializer.newInstance().initialize(); 
Greeting greeting = seContainer.select(Greeting.class).get(); 
greeting.printMessage("Hello World"); 
seContainer.close();

CDI bean是用select()方法,方法是将您要检索和使用的bean的类名传递给它。

配置选项

还可以对SeContext通过添加拦截器,扩展,替代项,属性和装饰器。

.enableInterceptors()
.addExtensions()
.selectAlternatives()
.setProperties()
.enableDecorators()

通过调用close()方法开启SeContainer或在使用用资源尝试结构,因为SeContainer扩展AutoCloseable接口。

5.Servlet 4.0:服务器推送

最后,但并非最不重要的是Servlet 4.0中的服务器推送特性,它将Servlet规范与HTTP/2对齐。

要理解这个特性,首先需要知道什么是服务器推送。

什么是服务器推送?

服务器推送是HTTP/2协议中的许多新特性之一,其设计目的是通过将这些资源推送到浏览器的缓存中来预测客户端的资源需求,以便当客户端发送对网页的请求并从服务器接收回响应时,它所需要的资源已经在缓存中。这是一个性能增强功能,可以提高网页加载的速度。

它是如何在Servlet4.0中公开的?

在Servlet4.0中,服务器推送特性通过PushBuilder实例,该实例从HttpServletRequest实例。

请看一下这段代码。您可以看到指向Header.png设置在PushBuilder实例通过path()方法,并通过调用push()当方法返回时,路径和条件标头将被清除,为构建器的重用做好准备。这个menu.css文件,然后推入ajax.jsJavaScript文件被推送到客户端。

protected void doGet(HttpServletRequest request, HttpServletResponse response) {

    PushBuilder pushBuilder = request.newPushBuilder();
    pushBuilder.path("images/header.png").push();
    pushBuilder.path("css/menu.css").push();
    pushBuilder.path("js/ajax.js").push();

    // Return JSP that requires these resources

}

到ServletdoGet()方法执行完毕,则资源将已到达浏览器。从JSP生成的HTML需要这些资源,不需要从服务器请求它们,因为它们已经是浏览器的缓存。