使用JAX RS简化REST应用开发

段落导航

REST 简介

REST 是英文 Representational State Transfer 的缩写,有中文翻译为“具象状态传输”。REST 这个术语是由 Roy Fielding 在他的博士论文 《 Architectural Styles and the Design of Network-based Software Architectures 》中提出的。REST 并非标准,而是一种开发 Web 应用的架构风格,可以将其理解为一种设计模式。REST 基于 HTTP,URI,以及 XML 这些现有的广泛流行的协议和标准,伴随着 REST,HTTP 协议得到了更加正确的使用。

相较于基于 SOAP 和 WSDL 的 Web 服务,REST 模式提供了更为简洁的实现方案。目前,越来越多的 Web 服务开始采用 REST 风格设计和实现,真实世界中比较著名的 REST 服务包括:Google AJAX 搜索 API、Amazon Simple Storage Service (Amazon S3)等。

基于 REST 的 Web 服务遵循一些基本的设计原则:

  1. 系统中的每一个对象或是资源都可以通过一个唯一的 URI 来进行寻址,URI 的结构应该简单、可预测且易于理解,比如定义目录结构式的 URI。

  2. 以遵循 RFC-2616 所定义的协议的方式显式地使用 HTTP 方法,建立创建、检索、更新和删除(CRUD:Create, Retrieve, Update and Delete)操作与 HTTP 方法之间的一对一映射:

    1. 若要在服务器上创建资源,应该使用 POST 方法;
    2. 若要检索某个资源,应该使用 GET 方法;
    3. 若要更改资源状态或对其进行更新,应该使用 PUT 方法;
    4. 若要删除某个资源,应该使用 DELETE 方法。
  3. URI 所访问的每个资源都可以使用不同的形式加以表示(比如 XML 或者 JSON),具体的表现形式取决于访问资源的客户端,客户端与服务提供者使用一种内容协商的机制(请求头与 MIME 类型)来选择合适的数据格式,最小化彼此之间的数据耦合。

JAX-RS – Java API for RESTful Web Services

Java EE 6 引入了对 JSR-311 的支持。JSR-311(JAX-RS:Java API for RESTful Web Services)旨在定义一个统一的规范,使得 Java 程序员可以使用一套固定的接口来开发 REST 应用,避免了依赖于第三方框架。同时,JAX-RS 使用 POJO 编程模型和基于标注的配置,并集成了 JAXB,从而可以有效缩短 REST 应用的开发周期。

JAX-RS 定义的 API 位于 javax.ws.rs 包中,其中一些主要的接口、标注和抽象类如 图 1所示。

图 1. javax.ws.rs 包概况

img

JAX-RS 的具体实现由第三方提供,例如 Sun 的参考实现 Jersey、Apache 的 CXF 以及 JBoss 的 RESTEasy。

在接下来的文章中,将结合一个记账簿应用向读者介绍 JAX-RS 一些关键的细节。

示例简介

记账簿示例应用程序中包含了 3 种资源:账目、用户以及账目种类,用户与账目、账目种类与账目之间都是一对多的关系。记账簿实现的主要功能包括:

  1. 记录某用户在什么时间花费了多少金额在哪个种类上
  2. 按照用户、账目种类、时间或者金额查询记录
  3. 对用户以及账目种类的管理

Resource 类和 Resource 方法

Web 资源作为一个 Resource 类来实现,对资源的请求由 Resource 方法来处理。Resource 类或 Resource 方法被打上了 Path 标注,Path 标注的值是一个相对的 URI 路径,用于对资源进行定位,路径中可以包含任意的正则表达式以匹配资源。和大多数 JAX-RS 标注一样,Path 标注是可继承的,子类或实现类可以继承超类或接口中的 Path 标注。

Resource 类是 POJO,使用 JAX-RS 标注来实现相应的 Web 资源。Resource 类分为根 Resource 类和子 Resource 类,区别在于子 Resource 类没有打在类上的 Path 标注。Resource 类的实例方法打上了 Path 标注,则为 Resource 方法或子 Resource 定位器,区别在于子 Resource 定位器上没有任何 @GET、@POST、@PUT、@DELETE 或者自定义的 @HttpMethod。清单 1展示了示例应用中使用的根 Resource 类及其 Resource 方法。

清单 1. 根 Resource 类

@Path("/") 
public class BookkeepingService { 
   ...... 
   @Path("/person/") 
   @POST 
   @Consumes("application/json") 
   public Response createPerson(Person person) { 
       ...... 
   } 
 
   @Path("/person/") 
   @PUT 
   @Consumes("application/json") 
   public Response updatePerson(Person person) { 
       ...... 
   } 
 
   @Path("/person/{id:\\d+}/") 
   @DELETE 
   public Response deletePerson(@PathParam("id") 
   int id) { 
       ...... 
   } 
 
   @Path("/person/{id:\\d+}/") 
   @GET 
   @Produces("application/json") 
   public Person readPerson(@PathParam("id") 
   int id) { 
       ...... 
   } 
 
   @Path("/persons/") 
   @GET 
   @Produces("application/json") 
   public Person[] readAllPersons() { 
       ...... 
   } 
 
   @Path("/person/{name}/") 
   @GET 
   @Produces("application/json") 
   public Person readPersonByName(@PathParam("name") 
   String name) { 
       ...... 
} 
......

参数标注

JAX-RS 中涉及 Resource 方法参数的标注包括:@PathParam、@MatrixParam、@QueryParam、@FormParam、@HeaderParam、@CookieParam、@DefaultValue 和 @Encoded。这其中最常用的是 @PathParam,它用于将 @Path 中的模板变量映射到方法参数,模板变量支持使用正则表达式,变量名与正则表达式之间用分号分隔。例如对 清单 1中所示的 BookkeepingService 类,如果使用 Get 方法请求资源”/person/jeffyin”,则 readPersonByName 方法将被调用,方法参数 name 被赋值为”jeffyin”;而如果使用 Get 方法请求资源”/person/123”,则 readPerson 方法将被调用,方法参数 id 被赋值为 123。要了解如何使用其它的参数标注 , 请参考 JAX-RS API。

JAX-RS 规定 Resource 方法中只允许有一个参数没有打上任何的参数标注,该参数称为实体参数,用于映射请求体。例如 清单 1 中所示的 BookkeepingService 类的 createPerson 方法和 updatePerson 方法的参数 person。

参数与返回值类型

Resource 方法合法的参数类型包括:

  1. 原生类型
  2. 构造函数接收单个字符串参数或者包含接收单个字符串参数的静态方法 valueOf 的任意类型
  3. List,Set,SortedSet(T 为以上的 2 种类型)
  4. 用于映射请求体的实体参数

Resource 方法合法的返回值类型包括:

  1. void:状态码 204 和空响应体
  2. Response:Response 的 status 属性指定了状态码,entity 属性映射为响应体
  3. GenericEntity:GenericEntity 的 entity 属性映射为响应体,entity 属性为空则状态码为 204,非空则状态码为 200
  4. 其它类型:返回的对象实例映射为响应体,实例为空则状态码为 204,非空则状态码为 200

对于错误处理,Resource 方法可以抛出非受控异常 WebApplicationException 或者返回包含了适当的错误码集合的 Response 对象。

Context 标注

通过 Context 标注,根 Resource 类的实例字段可以被注入如下类型的上下文资源:

  1. Request、UriInfo、HttpHeaders、Providers、SecurityContext
  2. HttpServletRequest、HttpServletResponse、ServletContext、ServletConfig

要了解如何使用第 1 种类型的上下文资源 , 请参考 JAX-RS API。

CRUD 操作

JAX-RS 定义了 @POST、@GET、@PUT 和 @DELETE,分别对应 4 种 HTTP 方法,用于对资源进行创建、检索、更新和删除的操作。

POST 标注

POST 标注用于在服务器上创建资源,如 清单 2所示。

清单 2. POST 标注

@Path("/") 
public class BookkeepingService { 
   ...... 
   @Path("/account/") 
   @POST 
   @Consumes("application/json") 
   public Response createAccount(Account account) { 
       ...... 
   } 
......

如果使用 POST 方法请求资源”/account”,则 createAccount 方法将被调用,JSON 格式的请求体被自动映射为实体参数 account。

GET 标注 待续,转载自IBM,源地址:https://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/

浮云 avatar
浮云
江天一色无纤尘,皎皎空中孤月轮。