使用JAX-RS创建RESTful Web Service

    本章介绍REST架构、RESTful web service和JAX-RS(Java API for RESTful Web Service,JSR 311)。
JAX-RS的参考实现Jersey实现了对JSR 311中定义的注解的支持,使得使用Java编程语言开发RESTful web service变得简单。
如果是使用GalssFish服务器,可以使用Update Tool安装Jersey例子和文档。使用Update Tool的教程见第62页的“Java EE 6教程组件”。Jersey例子和文档位于Update Tool的Available Add-ons中。

什么是RESTful Web Services

    RESTful web service是创建来能在web更好的运行的web service。REST是一种架构类型,指定了如统一的接口等应用于web service的约束。REST提供了如性能、可扩展性和可变性等特性,使得service能够更好的在web上工作。在REST框架中,数据和功能被认为是资源,是通过URI来访问的,通常是web链接。资源是通过使用一组简单的、定义良好的操作来生效。REST的架构方式限定了客户/服务器架构,是设计来使用无状态的通信协议的,通常是HTTP。在REST框架类型中,客户端和服务器使用标准的接口和协议交换资源的representation。
    下面的原则使得RESTful的应用程序简单、轻量并快捷:
    通过URI确定资源:一个RESTful的web service会公开一组资源,这组资源确定了和客户端互动的目标。资源是通过URI来确定的,URI为service和资源提供了全球的地址空间。更多的信息见第239页的“@Path注解和URI路径模版”。
    统一的接口:资源是通过固定的操作PUT,GET,POST和DELETE来创建、读取、修改和删除的。PUT会创建一个新的资源,DELETE会删除一个资源。GET会获取资源的当前状态。POST将资源的状态转变成新的值。更多信息见底241页的“对HTTP资源的响应”。
    自描述的消息:资源和它们的表现是解耦的,因此可以以不同的格式来访问,如HTML,XML,纯文本,PDF,JPEG,JSON等。关于资源的元数据是有效的并且用来完成控制缓存、检测传输错误、商讨合适的表现格式、执行身份验证和访问控制等。更多信息见第241页的“对HTTP资源的响应”和第243页的“使用实体提供者来映射HTTP response和request的实体段”。
    使用超链接的无状态的互动:和资源的互动都是无状态的,也就是说,request消息是自包含的。无状态的互动是基于显示状态转换的概念的。如URI重写、cookies和隐藏的表单字段等技术是为了交换状态而存在的。状态可以被嵌套在response消息中来指向互动的将来有效的状态。更多信息见“使用实体提供者来映射HTTP response和request的实体段”和JAX-RS Overview文档中的“Building URIs”。


创建RESTful的Web根资源类

    根资源类(Root resource classes)是由@Path注解标记的POJO或者至少有一个方法有@Path注解或请求方法指示符注解(@GET,@PUT,@POST或@DELETE)的POJO。
    资源方法(resource method)是资源类中含有请求方法指示符注解的方法。
    本节中将会解释怎样使用JAX-RS来注解Java类来创建RESTful的web service。
使用JAX-RS来开发RESTful web service
    JAX-RS是一个Java编程语言接口,被设计用来简化使用REST架构的应用程序的开发。
    JAX-RS API使用Java编程语言的注解来简化RESTful web service的开发。开发人员使用JAX-RS的注解修饰Java编程语言的类文件来定义资源和能够应用在资源上的行为。JAX-RS的注解是运行时的注解,因此运行时的映射会为资源生成辅助类和其他的辅助文件。包含JAX-RS资源类的Java EE应用程序中资源是被配置好的,辅助类和辅助文件是生成的,资源通过被发布到Java EE服务器上来公开给客户端。
    下表列出了JAX-RS定义的一些Java注解以及怎样使用它们的简要的描述。更进一步的JAX-RS的API见 http://download.oracle.com/javaee/6/api

注解

描述

@Path

@Path注解的值是一个相对的URI路径,这个路径指定了该Java类的位置,例如/helloworld。在这个URI中可以包含变量,例如可以获取用户的姓名然后作为参数传入URI中:/helloworld/{username}

@GET

@GET注解是请求方法指示符,这个指示符注解的Java方法会处理HTTPGET请求。资源的行为由资源回应的HTTP方法决定。

@POST

@POST注解是请求方法指示符,这个指示符注解的Java方法会处理HTTPPOST请求。资源的行为由资源回应的HTTP方法决定。

@PUT

@PUT注解是请求方法指示符,这个指示符注解的Java方法会处理HTTPPUT请求。资源的行为由资源回应的HTTP方法决定。

@DELETE

@DELETE注解是请求方法指示符,这个指示符注解的Java方法会处理HTTPDELETE请求。资源的行为由资源回应的HTTP方法决定。

@HEAD

@HEAD注解是请求方法指示符,这个指示符注解的Java方法会处理HTTPHEAD请求。资源的行为由资源回应的HTTP方法决定。

@PathParam

@PathParam注解是可以抽取并用在资源类中的一类参数。URIpath参数是从请求的URI中抽取的,而且参数的名称和@Path注解中定义的变量名对应。

@QueryParam

扫描二维码关注公众号,回复: 16515931 查看本文章
@QueryParam注解是可以抽取并在资源类中使用的一类参数。Query参数是从请求URI的查询参数中抽取的。

@Consumes

@Consumes注解是用来指定资源能够接受的客户发送的MIME媒体类型。

@Produces

@Produces注解用来指定资源能够生成并发送给客户端的MIME媒体类型,例如“text/plain”.

@Provider

@Provider注解用在任何对JAX-RS运行时(如MessageBodyReaderMessageBodyWriter)有意义的事物上。对HTTP请求,MessageBodyReader用来将HTTP请求实体段映射为方法参数。在响应的时候,返回的值使用MessageBodyWriter来映射成HTTP响应实体段。如果应用程序需要提供其他的元数据,如HTTP头或不同的状态代码,方法可以返回一个打包了实体的Response,该Response可以使用Response.ResponseBuilder创建。

JAX-RS应用程序概况
    下面的代码例子是一个非常简单的根资源类,使用了JAX-RS注解:
  1. package com.sun.jersey.samples.helloworld.resources;
  2. import javax.ws.rs.GET;
  3. import javax.ws.rs.Produces;
  4. import javax.ws.rs.Path;
  5. // The Java class will be hosted at the URI path "/helloworld"
  6. @Path("/helloworld")
  7. public class HelloWorldResource {
  8.         // The Java method will process HTTP GET requests
  9.         @GET
  10.         // The Java method will produce content identified by the MIME Media
  11.         // type "text/plain"
  12.         @Produces("text/plain")
  13.         public String getClichedMessage() {
  14.                 // Return some cliched textual content
  15.                 return "Hello World";
  16.         }
  17. }
复制代码
    随后的几节中我们会详细描述这个例子中使用的注解。
    @Path注解的值是一个相对的URI路径。在上面的例子中,这个Java类会放在/helloworld这个路径下。上面的例子中使用的是静态的URI路径,是最简单的例子。在URI中,我们可以包含变量,对于这样的包含变量的URI我们称为URI路径模板。
    @GET注解是一个请求方法指示符。在上面的例子中,被注解的Java方法会处理HTTP GET请求。
    @Produces注解用来指定资源能够生产和发送回客户端的MIME媒体类型。在上面的例子中,Java方法会生成MIME媒体类型“text/plain”。
    @Consumes注解用来指定资源能够消费的客户端发送的MIME媒体类型。我们可以将上面的例子中的代码修改为
  1. @POST
  2. @Consumes("text/plain")
  3. public void postClichedMessage(String message) {
  4. // Store the message
  5. }
复制代码
@Path注解和URI路径模板
    @Path注解指定了URI资源会响应的路径模板,是指定在资源的类级别或方法级别上。@Path注解的值是一个相对URI路径模板,这个路径是相对于资源发布的服务器的基础URI路径、应用程序的上下文根路径和JAX-RS运行时响应的URL。URI路径模板是包含变量的URI。这些变量在运行时会被取代,这样资源就能够根据被取代的URI来响应请求。变量是用花括号{}表示的,例如下面的例子
  1. @Path annotation:
  2. @Path("/users/{username}")
复制代码
    在这个例子中,用户会被提示输入自己的名字,然后一个被配置来响应这个URI路径模板的JAX-RS web service会响应该请求。例如,如果用户输入的名字是Galileo,这个web service会响应下面的URL http://example.com/users/Galileo.
要获取用户的名字,可以在请求方法的参数中使用@PathParam注解,如下面的代码所示:
  1. @Path("/users/{username}")
  2. public class UserResource {
  3.         @GET
  4.         @Produces("text/xml")
  5.         public String getUser(@PathParam("username") String userName) {
  6.         ...
  7.         }
  8. }
复制代码
    缺省的,URI变量必须符合正则表达式“[^/]+?”。开发人员也可以通过在变量名称后指定不同的正则表达式来指定客户化的变量模式。例如,如果用户名字必须是由大写或小写字母组成,可以在变量的定义中指定:
  1.         @Path("users/{username: [a-zA-Z][a-zA-Z_0-9]}")
复制代码
    在这个例子中,username这个变量只能匹配由大写或小写字母开头,后跟0个或多个字母、数字和下划线的用户名。如果用户名不匹配这个模板,那么一个404(Not Found)响应会被发送给客户端。
    @Path的值并不要求必须以/开始。无论是否以/开头或者开头是否有空格,JAX-RS运行时会一样的解析。
    一个URI路径模板可以包含一个或多个变量名,每个变量名都以前花括号{开始,以后花括号}结束。在上面的例子中,变量名是username。在运行时,被配置为响应上面的URI路径模板的资源会处理URI数据,将URI中对应{username}的部分作为username的变量数据。
    例如,如果你想要发布一个资源来响应URI路径模板 http://example.com/myContextRoot/resources/ {name1}/{name2}/,你需要将应用程序发布在一个Java EE服务器上,该服务器要响应对URI  http://example.com/myContextRoot 的请求,并使用如下的@Path注解来修饰你的资源:
  1. @Path annotation:
  2. @Path("/{name1}/{name2}/")
  3. public class SomeResource {
  4. ...
  5. }
复制代码
    在这个例子中,在web.xml文件中指定的JAX-RS辅助servlet的URLpattern是:
  1. <servlet-mapping>
  2. <servlet-name>My JAX-RS Resource</servlet-name>
  3. <url-pattern>/resources/*</url-pattern>
  4. </servlet-mapping>
复制代码
    在URI路径模板中,一个变量名可以被使用多次。
    如果变量的值中的字符和URI的保留字符冲突,那么该冲突的字符应该使用百分号编码代替。例如,变量值中的空格应该是一%20代替。
    下表中列出了一些URI路径模板的例子以及这些URI中的变量被替换后的结果,例子中使用保额变量名和值如下:
name1: james
name2: gatz
name3:
location: Main%20Street
question: why
注意:names的值是空字符串“”。

URI路径模板

               

替换后的URI

               
http://example.com/{name1}/{name2}/                                                
               
http://example.com/james/gatz/
               

http://example.com/{question}/{question}/{question}/

               

http://example.com/why/why/why/

               

http://example.com/maps/{location}

               

http://example.com/maps/Main%20Street

               
http://example.com/{name3}/home/
               
http://example.com//home
               

对HTTP资源的响应
    资源的行为是由资源响应的HTTP方法(GET,POST,PUT,DELETE)来决定的。
请求方法指示符注解
    请求方法指示符注解是由JAX-RS定义的运行时注解,对应同名的HTTP方法。在一个资源类文件中,HTTP方法通过使用请求方法指示符注解映射到Java编程语言的方法。一个资源的行为是由其要响应的HTTP方法决定的。JAX-RS为普通的HTTP方法定义了@GET,@POST,@PUT,@DELETE和@HEAD注解。开发人员也肯创建自己的客户化的请求方法指示符。创建客户化的请求方法指示符不在本教程的范围内。
    下面的例子是从storage service例子程序中抽取的,显示了怎样使用PUT方法来创建或更新storage容器:
  1. @PUT
  2. public Response putContainer() {
  3.         System.out.println("PUT CONTAINER " + container);
  4.         URI uri = uriInfo.getAbsolutePath();
  5.         Container c = new Container(container, uri.toString());
  6.         Response r;
  7.         if (!MemoryStore.MS.hasContainer(c)) {
  8.                 r = Response.created(uri).build();
  9.         } else {
  10.                 r = Response.noContent().build();
  11.         }
  12.         MemoryStore.MS.createContainer(c);
  13.         return r;
  14. }
复制代码
    缺省的,如果没有显示的实现对应的方法,JAX-RS运行时会自动的支持HEAD方法和OPTIONS方法。对HEAD方法,运行时会调用实现了的GET方法并忽略response实体。对OPTIONS,响应头Allow会被设置到资源支持的一组HTTP方法。另外,JAX-RS运行时会返回一个Web应用程序定义语言(WADL)文档来描述资源。更多的信息见 https://wadl.dev.java.net/
    由请求方法指示符修饰的方法必须返回void、Java编程语言的类型或javax.ws.rs.core.Response对象。可以使用PathParam或QueryParam注解来从URI中抽取多个参数,详细描述见第246页的“抽取request参数”。Java类型和实体段之间的转换是实体提供者(如MessageBodyReader和MessageBodyWriter)的责任。
    想要在response中提供额外的元数据方法应该返回一个Response类的实例。ResponseBuilder类使用builder模式提供了一个创建Response实例的简便的方法。HTTP PUT和POST方法期望有HTTP request体,因此应该对响应PUT和POST请求的方法使用MessageBodyReader。
    @PUT和@POST都能够被使用来创建和更新资源。POST可以表示任何事情,因此在使用POST时,由应用程序来定义其语义。PUT有定义好的语义。当使用PUT来创建的时候,客户声明了新创建的资源的URI。
    PUT有很明确的语义来创建和更新一个资源。客户发送的表述必须是使用GET收到的同样的表述,只是给出不同的媒体类型。PUT不允许一个资源被部分更新,这是使用PUT方法时的一个很常见的错误。一个通用的应用程序模式是使用POST类创建资源并返回一个201响应,将新创建的资源的URI的值设置为location头。这种模式下,web service声明了新创建的资源的URI。
使用实体提供者来映射HTTP Response和Request实体段
    实体提供者提供了在表述和相关的Java类型之间的映射服务。两种类型的实体提供者是MessageBodyReader和MessageBodyWriter。对于HTTP request,MessageBodyReader被用来将HTTP request实体段映射为方法参数。在response方面,使用MessageBodyWriter来将返回值映射为HTTP response实体段。如果应用程序需要提供附加的元数据,例如HTTP头或不同的状态码,方法可以返回一个包装了这些实体的Response实例,该实例可以用Response.ResponseBuilder创建。
下表显示了自动支持的标准的类型,只有当不使用这些标准类型的时候才需要编写实体提供者。

Java类型

支持的媒体类型

byte[]

所有的媒体类型(*/*

java.lang.String

所有的文本媒体类型(text/*

java.io.InputStream

所有的媒体类型(*/*

java.io.Reader

所有的媒体类型(*/*

java.io.File

所有的媒体类型(*/*

javax.activation.DataSource

所有的媒体类型(*/*

javax.xml.transform.Source

XML媒体类型(text/xml,application/xmlapplication/*+xml)

javax.xml.bind.JAXBElement和应用程序提供的JAXB

XML媒体类型(text/xml,application/xmlapplication/*+xml)

MultivaluedMap<String,String>

表单内容(application/x-www-form-urlencoder)

StreamingOutPut

所有的媒体类型(*/*),只对MessageBodyWriter有效

    下面的例子显示了怎样与@Consumes和@Provider注解一起使用MessageBodyReader:
  1. @Consumes("application/x-www-form-urlencoded")
  2. @Provider
  3. public class FormReader implements MessageBodyReader<NameValuePair> {
复制代码
    下面的例子显示了怎样与@Produces和@Provider注解一起使用MessageBodyWriter:
  1. @Produces("text/html")
  2. @Provider
  3. public class FormWriter implements
  4. MessageBodyWriter<Hashtable<String, String>> {
复制代码
    下面的例子显示了怎样使用ResponseBuilder:
  1. @GET
  2. public Response getItem() {
  3.         System.out.println("GET ITEM " + container + " " + item);
  4.         Item i = MemoryStore.MS.getItem(container, item);
  5.         if (i == null)
  6.                 throw new NotFoundException("Item not found");
  7.         Date lastModified = i.getLastModified().getTime();
  8.         EntityTag et = new EntityTag(i.getDigest());
  9.         ResponseBuilder rb = request.evaluatePreconditions(lastModified, et);
  10.         if (rb != null)
  11.                 return rb.build();
  12.         byte[] b = MemoryStore.MS.getItemData(container, item);
  13.         return Response.ok(b, i.getMimeType()).
  14.         lastModified(lastModified).tag(et).build();
  15. }
复制代码
使用@Consumes和@Produces来客户化Request和Response
    发送给资源的信息和传回客户端的信息都被指定了MIME媒体类型,是在HTTP request或response的头中指定的。可以使用下面的注解来指定资源能够响应或生产的MIME媒体类型:
  1. javax.ws.rs.Consumes
  2. javax.ws.rs.Produces
复制代码
    默认的,一个资源能够响应和生产所有的MIMIE媒体类型。
@Produces注解
    注解@Produces是用来指定一个资源能够产生并发送回客户端的MIME媒体类型或表现。如果@Produces是应用在类级别上,那么默认的资源的所有的方法都能够生产指定的MIME类型。如果是应用在方法级别上,那么这个注解会覆盖应用在类级别的@Produces注解。如果资源中没有方法能够生产客户端请求的MIME类型,那么JAX-RS运行时会发送回一个HTTP的“406 Not Acceptable”错误。
    注解@Produces的值是一个MIME类型的字符串数组,例如
  1. @Produces({"image/jpeg,image/png"})
复制代码
    下面的例子显示了怎样在类级别和方法级别应用@Produces注解:
  1. @Path("/myResource")
  2. @Produces("text/plain")
  3. public class SomeResource {
  4.         @GET
  5.         public String doGetAsPlainText() {
  6.                 ...
  7.         }
  8.         @GET
  9.         @Produces("text/html")
  10.         public String doGetAsHtml() {
  11.                 ...
  12.         }
  13. }
复制代码
    方法doGetAsPlainText()默认使用的是类级别上定义的@Produces注解指定的MIME媒体类型。方法doGetAsHtml上的@Produces注解覆盖了类级别的设置,因此该方法能够生成的是HTML类型,而不是普通文本。
    如果一个资源类能够生产超过一种MIME媒体类型,那么资源方法的选择就对应最能够接受的客户端声明的媒体类型。具体来说,HTTP请求的Accept头属性中声明了最可接受的MIME类型。例如,如果Accept头的值是Accept:text/plain,那么方法doGetAsPlainText会被调用。如果Accept头的值是Accept:text/plain;q=0.9,text/html,这声明了客户端能够接受媒体类型text/plain和test/html,但是更喜欢后者,因此doGetAsHtml方法会被调用。
    一个@Produces注解中可以声明多个媒体类型。下面的代码例子显示了怎样做到这点:
  1. @Produces({"application/xml", "application/json"})
  2. public String doGetAsXmlOrJson() {
  3.         ...
  4. }
复制代码
    当可接受的媒体类型是application/xml或application/json的时候这个doGetAsXmlOrJson方法会被调用。如果两个媒体类型是同样可接受的,那么会选择声明在前面的一个。
    上面的例子中,为了更明白,我们使用的是明确的MIME媒体类型。也可以使用相应的常量值,这样可以减少拼写错误。相关的信息见MediaType类的常量字段,位于 https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/core/MediaType.html
@Consumes注解
    注解@Consumes被用来指定资源能够接受或消费的来自客户端的MIME媒体类型。如果@Consumes是应用在类级别上的,该类的所有的响应方法默认的接受指定的MIME类型。如果是应用在方法级别上,那么方法级别上的@Consumes注解会覆盖应用在类级别上的@Consumes注解。
    如果资源不能够消费客户请求中的MIME类型,JAX-RS运行时会发送回一个HTTP 415 (“Unsupported Media Type”)错误。
    @Consumes注解的值是一个可接受的MIME类型的字符串数组。例如:
  1. @Consumes({"text/plain,text/html"})
复制代码
    下面的例子显示了怎样在类级别和方法级别上使用@Consumes注解。
  1. @Path("/myResource")
  2. @Consumes("multipart/related")
  3. public class SomeResource {
  4.         @POST
  5.         public String doPost(MimeMultipart mimeMultipartData) {
  6.                 ...
  7.         }
  8.         @POST
  9.         @Consumes("application/x-www-form-urlencoded")
  10.         public String doPost2(FormURLEncodedProperties formData) {
  11.                 ...
  12.         }
  13. }
复制代码
    方法doPost默认的接受类级别的@Consumes注解指定的MIME类型。方法doPost2的@Consumes注解覆盖了类级别的@Consumes注解,因此doPost2方法可接受的MIME类型是application/x-www-form-urencoded。
    如果没有任何的资源方法能够响应请求中的MIME类型,那么一个HTTP 415错误会被返回给客户端。
    本节中前面讨论的HelloWorld例子中,我们可以使用@Consume注解,如同我们下面的代码所做的
  1. @POST
  2. @Consumes("text/plain")
  3. public void postClichedMessage(String message) {
  4.         // Store the message
  5. }
复制代码
    在这个例子中,这个方法会消费由MIME媒体类型text/plain指定的表现。注意这里资源的方法返回的是void,这意味着没有任何表现被返回,因此一个状态码为HTTP 204(“No Content”)的响应会被返回。
提取请求参数
    资源方法的参数可能被添加了基于参数的注解来从请求中提取信息。在以前的例子中我们展现了时候@PathParam参数来从匹配@Path中声明的路径的request的URL中提取路径参数。
    可以在资源类中提取下面类型的参数:
  • Query
  • URI Path
  • Form
  • Cookie
  • Header
  • Matrix
    Query参数是从请求URI的查询参数中抽取的,在方法参数中使用javax.ws.rs.QueryParam注解来指定。下面的代码例子来自sparklines例子程序,演示了怎样使用@QueryParam注解来从请求URL中抽取query参数:
  1. @Path("smooth")
  2. @GET
  3. public Response smooth(
  4. @DefaultValue("2") @QueryParam("step") int step,
  5. @DefaultValue("true") @QueryParam("min-m") boolean hasMin,
  6. @DefaultValue("true") @QueryParam("max-m") boolean hasMax,
  7. @DefaultValue("true") @QueryParam("last-m") boolean hasLast,
  8. @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
  9. @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
  10. @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor
  11. ) { ... }
复制代码
    如果query参数step在请求URI的查询部分中存在,那么将从URI中抽取step的值并将其解析为32位的有符号整数并赋值给方法参数step。如果在请求URI的查询部分中不存在step参数,那么@DefaultValue注解所声明的缺省值2将被赋给方法参数step。如果step参数在请求URI中存在,但是无法被解析为32位的符号整数,那么一个HTTP 400(“Client Error”)响应将会被返回。
    用户自定义的Java编程语言类型也可以被用来作为query参数。下面的代码例子是上面的例子中使用的ColorParam类。
  1. public class ColorParam extends Color {
  2.         public ColorParam(String s) {
  3.                 super(getRGB(s));
  4.         }
  5.         private static int getRGB(String s) {
  6.                 if (s.charAt(0) == ’#’) {
  7.                         try {
  8.                                 Color c = Color.decode("0x" + s.substring(1));
  9.                                 return c.getRGB();
  10.                         } catch (NumberFormatException e) {
  11.                                 throw new WebApplicationException(400);
  12.                         }
  13.                 } else {
  14.                         try {
  15.                                 Field f = Color.class.getField(s);
  16.                                 return ((Color)f.get(null)).getRGB();
  17.                         } catch (Exception e) {
  18.                                 throw new WebApplicationException(400);
  19.                         }
  20.                 }
  21.         }
  22. }
复制代码
    类ColorParam的构造方法接受一个String作为参数。
    @QueryParam和@PathParam都只能被应用到以下的Java类型:
  • 除char之外的原始类型
  • 除Character之外的原始类型封装类
  • 有接受单独的字符串做参数的构造函数的类
  • 包含名为valueOf(String)的静态方法的类
  • List<T>,Set<T>,SortedSet<T>,这里T是上面所列的类型之一。有时候,同一个名字的参数可能包含多个值,在这种情况下,使用这些类型可以获取所有的值
    如果@DefaultValue没有被使用,在请求中又没有找到相应的query参数,那么对List,Set和SortedSet类型的参数其值是空的collection,对其他的对象类型值为null,对原始类型则是各自的默认值。
    URI路径参数是从request的URI中提取的,参数的名字对应类级别的@Path注解指定的URI路径模板中的变量名。在方法参数中使用javax.ws.rs.PathParam注解来指定URI路径参数。下面的例子显示了怎样使用@Path注解和在方法中使用@Path注解:
  1. @Path("/{username}")
  2. public class MyResourceBean {
  3.         ...
  4.         @GET
  5.         public String printUsername(@PathParam("username") String userId) {
  6.         ...
  7.         }
  8. }
复制代码
    在这个例子中,URI路径模板的变量名为username,该变量被指定为printUserName方法的参数。@PathParam注解的值被设置为变量名username。在运行的时候,printUserName被调用之前,username的值被从URI中提取出来并转换成字符串。转换的结果对printUserName方法生效并作为userId变量。
    如果路径模板的变量无法被转换成指定的类型,JAX-RS运行时会返回一个HTTP 400(“Bad Request”)错误给客户端。如果@PathParam注解不能转换成指定的类型,JAX-RS运行时会返回一个HTTP 404(“Not Found”)错误给客户端。
    @PathParam参数和其他的基于参数的注解(@MatrixParam,@HeaderParam,@CookieParam和@FormParam)遵守和@Query相同的规则。
    Cookie参数是使用javax.ws.rs.CookieParam注解的参数,这种参数会从cookie相关的HTTP头声明的cookie中提取信息。Header参数是使用javax.ws.rs.HeaderParam注解的参数,这种参数从HTTP头中提取信息。Matrix参数是使用javax.ws.rs.MatrixParam的参数,这种参数会从URL路径段中提取信息。Form参数是使用javax.ws.rs.FormParam的参数,这种参数从MIME类型是application/x-www-form-urlencoded的请求表现中提取信息并遵从HTML表单指定的编码,如同 http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 描述的一样。这种类型的参数对从以POST方式发送的HTML表单中提取信息很有用。
    下面的例子中我们从POST的表单数据中提取name参数:
  1. @POST
  2. @Consumes("application/x-www-form-urlencoded")
  3. public void post(@FormParam("name") String name) {
  4.         // Store the message
  5. }
复制代码
    要获得所有的query或path参数的参数名称和值的Map,使用如下的代码:
  1. @GET
  2. public String get(@Context UriInfo ui) {
  3.         MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
  4.         MultivaluedMap<String, String> pathParams = ui.getPathParameters();
  5. }
复制代码
    下面的方法获得header参数和cookie参数的名称和值的Map:
  1. @GET
  2. public String get(@Context HttpHeaders hh) {
  3.         MultivaluedMap<String, String> headerParams = ui.getRequestHeaders();
  4.         Map<String, Cookie> pathParams = ui.getCookies();
  5. }
复制代码
    通常,@Context被用来获取和request或response相关的上下文的Java类型。
对form参数,我们可以进行以下的操作:
  1. @POST
  2. @Consumes("application/x-www-form-urlencoded")
  3. public void post(MultivaluedMap<String, String> formParams) {
  4.         // Store the message
  5. }

推荐一篇文章:

一个草根程序员创业之路的所感所悟-2016 



猜你喜欢

转载自blog.csdn.net/gridlayout/article/details/23884221