RESTful 的webservice
??
JAX-RS (JSR-311) 是为 Java EE 环境下的 RESTful 服务能力提供的一种规范。它能提供对传统的基于 SOAP 的 Web 服务的一种可行替代。 在本文中,了解 JAX-RS 的主要组件。本文用一个例子展示了一个企业如何使用 JAX-RS 内的功能以一种 Restful 的方式公开员工的联系信息。 回页首 背景多年来,开发人员使用各种工具在其 Java 应用程序内创建 RESTful 服务。由于 REST 架构的简单性,主要需求 — 接收 HTTP 消息和头部的能力 — 可以由一个简单的 Java Web 容器实现。 Java servlets 常被用来开发 RESTful 应用程序。如何使用 servlet 并没有固定的模式。通常,servlet 会接受请求并自己解析这个 HTTP 请求 URI,以将此请求与一个已知资源相匹配。对于 REST 服务开发,这个简单的 servlet 模型以更为正式的 API 得到扩展。但是,因为这些 API 是在 servlet 模型之上开发的,所以这些 API 中没有一个是作为正式的标准开发的。 随着 REST 越来越多地被采用为一种架构,Java Community Process (JCP) 计划在未来的 Java Enterprise Edition 6 发布版中包括对 REST 的正式支持。JSR-311 也已创建好,并已有了 JAX-RS 1.0 规范,提供了一种新的基于注释的方式来开发 RESTful 服务。与 servlet 模型相比,JAX-RS 注释让您能集中于您的资源和数据对象。并且,您不必再开发通讯层(通过 servlet)。 回页首 Java 资源JAX-RS 建立了一种特殊的语言来描述资源,正如由其编程模型所表示的。有五种主要条目:根资源、子资源、资源方法、子资源方法以及子资源定位器。 根资源根资源是由 清单 1. JAX-RS 根资源package com.ibm.jaxrs.sample.organization; import javax.ws.rs.Path; @Path(value="/contacts") public class ContactsResource { ... } 子资源子资源是作为 subresource locator 调用的结果返回的 Java 类。它们类似于根资源,只不过它们不是由 清单 2. JAX-RS 子资源package com.ibm.jaxrs.sample.organization; import javax.ws.rs.GET; public class Department { @GET public String getDepartmentName() { ... } } 如上所示的清单 2 展示了由 资源方法资源方法是根资源或子资源内绑定到 HTTP 方法的 Java 方法。绑定是通过诸如 清单 3. JAX-RS 资源方法package com.ibm.jaxrs.sample.organization; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path(value="/contacts") public class ContactsResource { @GET public List<ContactInfo> getContacts() { ... } } 在清单 3 的例子中,发送到 子资源方法子资源方法非常类似于资源方法;惟一的区别是子资源方法也是由 清单 4. JAX-RS 子资源方法package com.ibm.jaxrs.sample.organization; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path(value="/contacts") public class ContactsResource { @GET public List<ContactInfo> getContacts() { ... } @GET @Path(value="/ids") public List<String> getContactIds() { ... } } 在清单 4 中,发送到 子资源定位器子资源定位器是能进一步解析用来处理给定请求的资源的一些方法。它们非常类似于子资源方法,因它们具备一个 清单 5. JAX-RS 子资源定位器package com.ibm.jaxrs.sample.organization; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path(value="/contacts") public class ContactsResource { @GET public List<ContactInfo> getContactss() { ... } @GET @Path(value="/ids") public List<String> getContactIds() { ... } @Path(value="/contact/{contactName}/department") public Department getContactDepartment(@PathParam(value="contactName") String contactName) { ... } } 在上述例子中,对 回页首 注释本节将会探讨一些重要的注释及其使用。对于由 JAX-RS 规范提供的注释的完整列表,可以参考本文的 参考资料 部分给出的 JSR-311 链接。 @Path
清单 6. @Path 的使用package com.ibm.jaxrs.sample.organization; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path(value="/contacts") public class ContactsResource { @GET @Path(value="/{emailAddress:.+@.+.[a-z]+}") public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") String emailAddress) { ... } @GET @Path(value="/{lastName}") public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) { ... } }
@GET、@POST、@PUT、@DELETE、@HEAD@GET、@POST、@PUT、@DELETE 以及 @HEAD 均是 HTTP 请求方法指示符注释。您可以使用它们来绑定根资源或子资源内的 Java 方法与 HTTP 请求方法。HTTP GET 请求被映射到由 @GET 注释的方法;HTTP POST 请求被映射到由 @POST 注释的方法,以此类推。用户可能还需要通过使用 清单 7. 定制的 HTTP 请求方法指示符注释package com.ibm.jaxrs.sample.organization; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.ws.rs.HttpMethod; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @HttpMethod("GET") public @interface CustomGET { } 上述的声明定义了 @Conumes 和 @Produces
清单 8. @Consumes/@Producespackage com.ibm.jaxrs.sample.organization; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path(value="/contacts") public class ContactsResource { @GET @Path(value="/{emailAddress:.+@.+.[a-z]+}") @Produces(value={"text/xml","application/json"}) public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") String emailAddress) { ... } @GET @Path(value="/{lastName}") @Produces(value="text/xml") public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) { ... } @POST @Consumes(value={"text/xml","application/json"}) public void addContactInfo(ContactInfo contactInfo) { ... } } 对于上述的 在清单 9 中, 清单 9. Content-Type 头部的使用POST /contacts HTTP/1.1 Content-Type: application/json Content-Length: 32 相反地, 清单 10. Accept 头部的使用GET /contacts/johndoe@us.ibm.com HTTP/1.1 Accept: application/json 在清单 10 中,对 /contacts/johndoe@us.ibm.com 的 回页首 ProvidersJAX-RS 提供程序是一些应用程序组件,允许在三个关键领域进行运行时行为的定制:数据绑定、异常映射以及上下文解析(比如,向运行时提供 JAXBContext 实例)。每个 JAX-RS 提供程序类必须由 MessageBodyWriterMessageBodyWriters 被 JAX-RS 运行时用来序列化所返回资源的表示。遵从 JSR-311 的运行时提供了对常见类型(java.lang.String、java.io.InputStream、 JAXB 对象等)的本机支持,但用户也可以向 JAX-RS 运行时提供他或她自己的 MessageBodyWriter。比如,您可以提供一个定制 清单 11. 定制 MessageBodyWriterpackage com.ibm.jaxrs.sample.organization; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; @Provider @Produces("text/xml") public class ContactInfoWriter implements MessageBodyWriter<ContactInfo> { public long getSize(T t,java.lang.Class<ContactInfo> type,java.lang.reflect.Type genericType,java.lang.annotation.Annotation[] annotations,MediaType mediaType) { ... } public boolean isWriteable(java.lang.Class<ContactInfo> type,MediaType mediaType) { return true; } public void writeTo(ContactInfo contactInfo,MediaType mediaType,MultivaluedMap< java.lang.String,java.lang.Object> httpHeaders,java.io.OutputStream entityStream) { contactInfo.serialize(entityStream); } }
MessageBodyReaderMessageBodyReaders 则与 MessageBodyWriters 相反。对于反序列化,JAX-RS 运行时支持与序列化相同的类型。用户也可以提供他或她自己的 MessageBodyReader 实现。MessageBodyReader 的最主要的功能是读取请求 清单 12. 定制 MessageBodyReaderpackage com.ibm.jaxrs.sample.organization; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.Provider; @Provider @Consumes("text/xml") public class ContactInfoReader implements MessageBodyReader<ContactInfo> { public boolean isReadable(java.lang.Class<ContactInfo> type,MediaType mediaType) { return true; } public ContactInfo readFrom(java.lang.Class<ContactInfo> type,java.lang.String> httpHeaders,java.io.InputStream entityStream) { return ContactInfo.parse(entityStream); } } 与 MessageBodyWriter (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |