加载中

When JAX-RS 1.0 was first unveiled back in 2008 by JSR-311 spec leads Marc Hadley and Paul Sandoz, it became one of the first POJO/Annotation based frameworks for creating robust web-based applications.

Now five years later Java EE 7 has been released and it includes the latest JAX-RS version 2.0, the realization of JSR-339 led by Marek Potociar and Santiago Pericas-Geertsen. We will look at some of the features that make JAX-RS 2.0 worth the upgrade, but first let's take a quick refresher view of JAX-RS 1.0.

@Path(portfolios) 
public class PortfolioResource { 
   
  @GET 
  public Collection<Portfolio> allPortfolios() { 
    . . . 
  } 
   
  @GET 
  public Portfolio getPortfolio(
       @PathParam("portfolioId") String id) { 
    . . .
  }
}

当JAX-RS 1.0在2008年第一次由JSR-311——特别是其领导者Marc Hadley和Paul Sandoz——公之于众的时候,它就成为了第一个基于POJO/Annotation的、用于创建健壮的Web应用的框架。

现在五年过去了,Java EE 7已经发布并且它包含了最新的JAX-RS 2.0版本,JSR-339的实现由Marek Potociar和Santiago Pericas-Geertsen发起。我们将拭目以待一些新特性,它们将使得升级到JAX-RS 2.0变得有意义,但是首先,我们先来快速的回顾一下JAX-RS 1.0。

@Path(portfolios) 
public class PortfolioResource { 
   
  @GET 
  public Collection<Portfolio> allPortfolios() { 
    . . . 
  } 
   
  @GET 
  public Portfolio getPortfolio(
       @PathParam("portfolioId") String id) { 
    . . .
  }
}
In the above listing, line 1 says to map this resource to the relative path /portfolios. Line 4 says that a GET request should return all portfolios. Lines 9 & 10 indicate that a GET request with, for example, URI /portfolios/123 should extract the parameter (e.g. 123) following the resource URI (e.g. portfolios), and assign it to the variable "id", then return the associated portfolio.

That syntax remains in JAX-RS 2.0.

Consistent with the central theme of Java EE 7, JAX-RS 2.0 adds some long awaited features mostly focused around what Oracle calls its "simplified API".

These features can be categorized as:

  • Client API
  • Async
  • HATEOAS (Hypermedia)
  • Annotations
  • Validation
  • Filters and Handlers
  • Content negotiation

在上面的列表中,第一行表示把这个资源映射到相关的路径/文件夹。第四行表示一个GET请求应该返回所有的文件夹。第九行和第十行表明一个GET请求,例如带有URI/文件夹/123的请求,应该提起出紧跟在资源URI(例如:文件夹)之后的参数(例如:123),并且把它声明为变量“id”,之后返回重组的文件夹。

这个语法在JAX-RS 2.0中任然保留。

与Java EE 7的核心主题相一致,JAX-RS 2.0添加了一些期待已久的特性,这些特性主要围绕Oracle所称的“简化API”。

这些特性可以这样分类:

  • 客户端API
  • 异步
  • HATEOAS(超媒体)
  • 注释
  • 验证
  • 过滤器与处理程序
  • 内容协商
We will take a quick look at each of these categories:

Client API
JAX-RS 1.0 was strictly a server side API. Some implementations provided varying degrees of client support but generally the developer was left to install something ad-hoc like the Apache Software Foundation's Jakarta Commons HttpClient or WizTools REST Client.

JAX-RS 2.0 adds "builder" tools for calling a web service from the client. Here is a sample:

  Client client=ClientFactory.newClient();
  String shares=client.target("http://.../portfolio/123")
      .pathParam("identifier", "IBM")
      .queryParameter("identifierType", "ticker")
      .request("text/plain).get(String.class");

You can see that this method first obtains a client, and then uses the builder pattern to construct all of the parameters of the URL, allowing the application developer to formulate the URL without dealing with the vagaries of the URL construction.

我们将快速的看一下每个分类:

客户端API

JAX-RS 1.0是一个严格的客户端API,一些实现对客户端提供了各种等级的支持,但是通常开发人员会安装像Apache软件基Jakarte公共组件中的HttpClient 或 WizTools的 REST Client

JAX-RS 2.0 为客户端调用Web服务添加了一个"构建" 工具:

  Client client=ClientFactory.newClient();
  String shares=client.target("http://.../portfolio/123")
      .pathParam("identifier", "IBM")
      .queryParameter("identifierType", "ticker")
      .request("text/plain).get(String.class");

我们看,这个方法首先包含了一个客户端(client),然后使用了构建模式来构造URL的所有参数,同时,允许开发人员不需要使用各种各样的URL构造器来规划URL。

This approach is especially useful for calls with an HTTP body, such as HTTP POST and HTTP PUT. The following example allows the application to sell 100 shares of IBM:

Stock stock=client.target("http://.../portfolio/123/sell")
        .pathParam("identifier", "IBM")
        .queryParameter("identifier", "ticker")
        .request("application/json")
        .post(text("100", Shares.class));

Async
In JAX-RS 1.0, a calling client had to wait for the response from the server. 2.0 introduces asynchronous support. This allows a client to make a RESTful call, and optionally get a Future or an InvocationCallback to be notified when the response is complete.

HATEOAS (Hypermedia)
According to strict RESTafarian Orthodoxy if you are not using HATEOAS you are not doing REST! HATEOAS (Hypermedia as the Engine of Application State) requires the RESTful producers and consumers to agree on a set of links to be returned in each call, for navigating to the next step. If you think of REST as an application version of a web page, then HATEOAS can be thought of as the links within a web page.

JAX-RS 2.0 provides Link and Target classes for introducing hyperlinks into a response on the server side and reacting to them on the client.

这个方法对于一个带有HTTP正文的请求来讲尤其有效,例如HTTP POST和HTTP PUT。下面的例子让应用能够出售100股的IBM:

Stock stock=client.target("http://.../portfolio/123/sell")
        .pathParam("identifier", "IBM")
        .queryParameter("identifier", "ticker")
        .request("application/json")
        .post(text("100", Shares.class));

异步
在JAX-RS 1.0中,一个要调用的客户端需要等待服务器传回的响应。2.0嵌入了异步支持。这让一个客户端能够发起一个REST的调用,并且在响应完成的时候得到一个Future或者一个InvocationCallback作为通知。

HATEOAS(超媒体)
根据严格的RESTafarian规范,如果你没有使用HATEOAS,你就不是在做REST!HATEOAS(作为应用状态引擎的超媒体)要求REST的生产者和客户在“每个调用返回一组链接”上达成共识,以便进行下一步。如果你认为REST是一个应用版本的Web页,那么HATEOAS就可以认为是包含一组Web页面的链接。

JAX-RS 2.0提供了Link和Target类,来把超链接嵌入到一个服务器端的响应当中,并把它们响应到客户端去。

Annotations
New annotations have been introduced, for example to support new injections.

Bean Validation
An annotation-based facility for specifying parameter meta-data. For example "@NotNull shares" indicates that the "shares" parameter may not be null. You can also supply custom annotation for example to ensure certain data formats such as a zip code or phone number.

Filters and Handlers
The Filters API provides the ability to chain servlet filters in a chain of responsibility pattern. This is useful for introducing orthogonal concerns such as logging. Any filter can decide to continue or terminate the chain by calling FilterAction.NEXT or FilterAction.STOP respectively.

Handlers are similar to Filters except they wrap a method invocation at a specified extension point. This is useful for intercepting calls at that extension point, for example to massage or enrich the payload data.

注释
新的注释已经嵌入,例如支持新的注入。

Bean验证
一个基于注释的机制来识别参数的meta-data。例如“@NotNull shares”代表“shares”参数不允许为null。你同样可以提供传统的注释,比如保证特定的数据格式,例如邮编或者电话号码。

过滤器与处理程序
过滤器API提供了在一个响应模式链中链入servlet过滤器的能力。这对于嵌入正统的概念来过很有用,比如登入。任意过滤器都能够通过调用FilterAction.NEXT或者FIlterAction.STOP来各自决定是继续还是终止链。

处理程序与过滤器很相似,只不过他们在特定的扩展点中包含了一个方法调用。这对于扩展点的获取调用来讲很有用,例如调整或者丰富负载数据。

Content negotiation
Richer annotations for @Accepts and @Produces parameters allow you to prioritize request/response formats.

JAX-RS is still missing a good security model, which makes it difficult to use in an external facing enterprise application. We hope the next release will provide support for point to point authentication.

It may be some time before the main JEE containers provide support for JAX-RS 2.0. Meanwhile you can take advantage immediately by deploying the latest version of Jersey with your application. Oracle has published steps for doing so in WebLogic 12c.

For more information, please see the OTN article Java EE 7 and JAX-RS 2.0 by JSR 339 expert group member Adam Bien

内容协商
@Accepts和@Produces参数更丰富的注释,让你可以优先处理请求/响应格式。

JAX-RS仍旧缺失一个好的安全模型,这使得使用外部的企业应用有些困难。我们希望下一个发布版本将会提供对于点对点认证的支持。

距离JEE容器提供JAX-RS 2.0的支持可能还有一段时间。然而你可以通过在你的应用中部署最新版本的Jersey来立即获益。Oracle已经发布了在WebLogic 12c中实施的步骤

更多的信息,请看OTN的文章Java EE 7与JAX-RS 2.0,它由JSR 339专家团队成员Adam Bien所作。

返回顶部
顶部