leftso 857 0 2018-04-03 20:33:07

前言

    备受期待的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平台近四年来的第一个版本,它包含数百个新功能,更新的功能和错误修复。那么最好的新功能是什么?

前5个新功能

  • 新的安全API:注释驱动的身份验证机制
全新的安全API包含三项出色的新功能:身份库抽象,新的安全上下文以及新的注释驱动的身份验证机制,这些机制会使web.xml文件声明过时。最后一个是我今天要讨论的内容。
  • JAX-RS 2.1:新的被动式客户
端JAX-RS 2.1中的新型被动式客户端,采用反应式编程风格并允许组合端点结果。
  • 新的JSON绑定API
新的JSON绑定API,为JSON序列化和反序列化提供本机Java EE解决方案。
  • CDI 2.0:在Java SE中使用CDI 2.0中
有趣的新功能允许在Java SE应用程序中引导CDI。
  • Servlet 4.0:服务器推送Servlet 4.0中
的服务器推送功能将servlet规范与HTTP / 2对齐。
 

1.新的安全API

有可能添加到Java EE 8中的最重要的新功能是新的安全API。这个新API的主要动机是简化,标准化和现代化跨容器和实现处理安全问题的方式。

Web认证的配置已经实现了现代化,这要归功于三个使web.xml文件声明成为冗余的新注释。稍后再说。

新的安全上下文 API标准化了servlet和EJB容器执行身份验证的方式

新的Identity存储抽象简化了身份存储的使用。

所以我们来看看这些新增的第一个。

注释驱动的认证机制

此功能全部是关于配置网络安全。web.xml文件中的哪个传统所需的XML声明。
 

由于HttpAuthenticationMechanism接口代表了HTTP身份验证,并且随附了三个内置的启用CDI的实现,这些实现代表了网络安全可以配置的三种方式之一,这已不再是必需的。

他们触发使用这些注释之一。

@BasicAuthenticationMechanismDefinition
@FormAuthenticationMechanismDefinition
@CustomFormAuthenticationMechanismDefinition

它们替换了servlet容器中已有的传统HTTP基本认证,基于表单和自定义表单的认证功能已经在servlet容器中了。

例如,要启用基本身份验证,所需做的一切就是将@BasicAuthenticationMechanismDefinition注释添加到您的servlet,就像下面这样。

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

现在,您可以舍弃XML配置,并使用其中一个新注释来启用网络安全。

 

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

我们来看看JAX-RS 2.1中新的被动客户端以及它如何采用反应式编程风格。

被动方法的核心是数据流的概念,其中执行模型通过流传播更改。一个典型的例子是JAX-RS方法调用。当调用返回时,将对方法调用的结果执行下一个操作(可能是继续,完成或错误)。

您可以将其视为异步流程的流程,下一个流程将根据前一个流程的结果进行操作,然后将流程结果传递给链中的下一个流程。数据流是可组合的,因此您可以将许多流合并并转换为一个结果。

通过调用用于构造客户端实例的Invocation.Builder实例上的rx()方法来启用反应性功能。它的返回类型是具有参数化响应类型CompletionStage。该CompletionStage接口是用Java 8中引入,并提出了一些有趣的可能性。

例如,在这个代码片段中,两个调用是对不同的端点进行的,然后将结果合并:

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,此API为JSON序列化和反序列化提供了原生Java EE解决方案

以前,如果您想要将JSON序列化和反序列化,则必须依赖Jackson或GSON等第三方API。不再。使用新的JSON绑定API,您可以使用本地可用的所有功能。

从Java对象生成JSON文档并不那么简单。只需调用toJson()方法并将它传递给想要序列化的实例即可。

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

行为定制

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

例如,您可以使用@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容器。这是通过调用SeContainerInitializer抽象类静态方法  newInstance()来实现的。它返回一个SeContainer实例,该实例是CDI运行时的句柄,您可以使用该句柄执行CDI解析,如此代码片段中所示。它可以访问作为CDI核心入口点的BeanManager。
 

SeContainer seContainer =
       SeContainerInitializer.newInstance().initialize();
 Greeting greeting = seContainer.select(Greeting.class).get();
 greeting.printMessage("Hello World");
 seContainer.close();
使用select()方法检索CDI bean,方法是传递要检索和使用的bean的类名称。

配置选项

可以通过添加拦截器,扩展,替代方法,属性和装饰器来进一步配置SeContext

.enableInterceptors()
.addExtensions()
.selectAlternatives()
.setProperties()
.enableDecorators()
通过在SeContainer上调用close()方法手动关闭容器,或者在使用Try  -with-resources结构时自动关闭容器,因为SeContainer  扩展了AutoCloseable  接口。

5. Servlet 4.0:服务器推送

最后但并非最不重要的一点是,Servlet 4.0中的服务器推送功能使servlet规范与HTTP / 2保持一致。

要理解此功能,您首先需要知道服务器推送的内容。

什么是服务器推送?

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

它如何在Servlet 4.0中公开?

在Servlet 4.0中,Server Push功能通过HttpServletRequest实例获得PushBuilder实例公开

看看这段代码片段。您可以看到,通过path()方法在PushBuilder实例上设置了header.png路径,并通过调用push()将其推送到客户端。当方法返回时,路径和条件头部将被清除,以便构建器重用。该menu.css文件推,然后ajax.js javascript文件推送到客户端。

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
 
}
在Servlet doGet()方法完成执行时,资源将到达浏览器。从JSP生成的需要这些资源的HTML不需要从服务器请求它们,因为它们已经是浏览器缓存。