REST

REpresentational State Transfer代表性状态传输、具象状态传输

REST定义了应该如何正确地使用Web标准,例如HTTP和URI。REST并非标准,而是一种开发 Web 应用的架构风格,可以将其理解为一种设计模式。

REST关键原则

1、为所有“事物”定义ID

含义:

在Web中,代表ID的统一概念是:URI。URI构成了一个全局命名空间,使用URI标识你的关键资源意味着它们获得了一个唯一、全局的ID。

使用URI标识所有值得标识的事物,特别是应用中提供的所有“高级”资源,无论这些资源代表单一数据项、数据项集合、虚拟亦或实际的对象还是计算结果等。

好处:

使用唯一、全局统一的命名规则的好处,既适用于浏览器中的Web应用,也适用于机对机(machine-to-machine,m2m)通信。

2、将所有事物链接在一起

含义:

任何可能的情况下,使用链接指引可以被标识的事物(资源)。

正式描述:“超媒体被当作应用状态引擎(Hypermedia as the engine of application state)”,有时简写为HATEOAS。这个描述的核心是超媒体概念,换句话说:是链接的思想

好处:

超媒体原则还有一个更重要的方面——应用“状态”。简而言之,实际上服务器端为客户端提供一组链接,使客户端能通过链接将应用从一个状态改变为另一个状态。目前,只需要记住:链接是构成动态应用的非常有效的方式.

[html] view plain copy  print?

  1. <order self="http://example.com/customers/1234">
  2. <amount>23</amount>
  3. <product ref="http://example.com/products/4554">
  4. <customer ref="http://example.com/customers/1234">
  5. </customer>
  6. </product>
  7. </order>

3、使用标准方法

含义:

浏览器知道如何去处理URI的原因在于所有的资源都支持同样的接口,一套同样的方法集合。标准方法集合包含GET、POST\PUT、DELETE、HEAD和OPTIONS

为使客户端程序能与你的资源相互协作,资源应该正确地实现默认的应用协议(HTTP),也就是使用标准的GET、PUT、POST和DELETE方法。

好处:

它使你的应用成为Web的一部分——应用程序为Web变成Internet上最成功的应用所做的贡献,与它添加到Web中的资源数量成比例。采用RESTful方式,一个应用可能会向Web中添加数以百万计的客户URI

统一接口也使得所有理解HTTP应用协议的组件能与你的应用交互。通用客户程序(generic client)就是从中受益的组件的例子,例如curl、wget、代理、缓存、HTTP服务器、网关还有Google、Yahoo!、MSN等等。

4、资源多重表述?

含义:

客户程序如何知道该怎样处理检索到的数据,比如作为GET或者POST请求的结果?原因是,HTTP采取的方式是允许数据处理和操作调用之间关系分离的。

针对不同的需求提供资源多重表述

好处:

如果你为你的资源提供HTML和XML两种表述方式,那这些资源不仅可以被你的应用所用,还可以被任意标准Web浏览器所用

5、无状态通信

含义:

REST要求状态要么被放入资源状态中,要么保存在客户端上。或者换句话说,服务器端不能保持除了单次请求之外的,任何与其通信的客户端的通信状态。

这样做的最直接的理由就是可伸缩性—— 如果服务器需要保持客户端状态,那么大量的客户端交互会严重影响服务器的内存可用空间

好处:

无状态约束使服务器的变化对客户端是不可见的,因为在两次连续的请求中,客户端并不依赖于同一台服务器。

JAX-RS

Java API forRESTful WebServices旨在定义一个统一的规范,使得 Java 程序员可以使用一套固定的接口来开发 REST 应用,避免了依赖于第三方框架。是一个Java编程语言的应用程序接口,支持按照表象化状态转变 (REST)架构风格创建Web服务Web服务。

与传统的 servlet 模型相比,JAX-RS 提供了一种可行的、更为简便、移植性更好的方式来在 Java 内实现 RESTful 服务。使用注释让您能够轻松提供 Java 资源的路径位置并将 Java 方法绑定到 HTTP 请求方法。一种可移植的数据绑定架构提供了一些本机的 Java 类型支持并允许进行序列化/反序列化处理的完全定制。javax.ws.rs.core.Application 子类的扩展以及 web.xml 内的相应清单表明了用最少的部署描述符配置就能进行轻松部署。

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

JAX-RS标注

JAX-RS提供了一些标注将一个资源类,一个POJO类,封装为Web资源。标注包括:

@Path,标注资源类或方法的相对路径

@GET,@PUT,@POST,@DELETE,标注方法是用的HTTP请求的类型,分别对应 4 种 HTTP 方法,用于对资源进行创建、检索、更新和删除的操作。

  • 若要创建资源,应该使用 POST 方法;
  • 若要检索某个资源,应该使用 GET 方法;
  • 若要更改资源状态或对其进行更新,应该使用 PUT 方法;
  • 若要删除某个资源,应该使用 DELETE 方法。

@Produces,标注返回的MIME媒体类型

@Consumes,标注可接受请求的MIME媒体类型

@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,

  • @PathParam来自于URL的路径,
  • @QueryParam来自于URL的查询参数,
  • @HeaderParam来自于HTTP请求的头信息,
  • @CookieParam来自于HTTP请求的Cookie。

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

[java] view plain copy  print?

  1. @Path("/")
  2. public class BookkeepingService {
  3. ......
  4. @Path("/person/") //资源方法;若无@POST,则为子资源定位器
  5. @POST
  6. @Consumes("application/json")
  7. public Response createPerson(Person person) { //JSON 格式的请求体被自动映射为实体参数person
  8. ......
  9. }
  10. @Path("/person/")
  11. @PUT
  12. @Consumes("application/json")
  13. public Response updatePerson(Person person) {
  14. ......
  15. }
  16. @Path("/person/{id:\\d+}/") //正则表达式
  17. @DELETE
  18. public Response deletePerson(@PathParam("id")
  19. int id) {
  20. ......
  21. }
  22. @Path("/person/{id:\\d+}/")
  23. @GET
  24. @Produces("application/json")
  25. public Person readPerson(@PathParam("id")
  26. int id) {
  27. ......
  28. }
  29. @Path("/persons/")
  30. @GET
  31. @Produces("application/json")
  32. public Person[] readAllPersons() { //数组类型的返回值被自动映射为 JSON 格式的响应体——?
  33. ......
  34. }
  35. @Path("/person/{name}/")
  36. @GET
  37. @Produces("application/json")
  38. public Person readPersonByName(@PathParam("name")
  39. String name) {
  40. ......
  41. }

注意:

  1. Subresources Locators是指一个指定了@Path annotation,但未指定HttpMethod的annotation
  2. 最好是在一个interface中定义这个标注,然后实现这个interface

Resource方法参数类型、返回类型

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

  1. 原生类型 ——在客户端如何发送原生类型?可否发送JSON类?
  2. 构造函数接收单个字符串参数,或者包含拥有一个static的valueOf(String)方法
  3. List<T>,Set<T>,SortedSet<T>(T 为以上的 2 种类型)
  4. 用于映射请求体的实体参数

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

  1. void:状态码 204 和空响应体
  2. Response:Response 的 status 属性指定了状态码,entity 属性映射为响应体

    [java] view plain copy  print?

    1. return Response.status(Status.OK).entity(JsonUtils.toString(result)).build();
  3. GenericEntity:GenericEntity 的 entity 属性映射为响应体,entity 属性为空则状态码为 204,非空则状态码为 200
  4. 其它类型:返回的对象实例映射为响应体,实例为空则状态码为 204,非空则状态码为 200

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

内容协商与数据绑定

Web 资源可以有不同的表现形式,服务端与客户端之间需要一种称为内容协商(Content Negotiation)的机制:

作为服务端,Resource 方法的@Produces 标注用于指定响应体的数据格式(MIME 类型),@Consumes 标注用于指定请求体的数据格式;

作为客户端,Accept 请求头用于选择响应体的数据格式,Content-Type 请求头用于标识请求体的数据格式。

——Produces=Accept?Consumes=Content-Type?

服务端:@Produces,@Consumes

[java] view plain copy  print?

  1. @GET
  2. @Path(value="/{emailAddress:.+@.+\\.[a-z]+}")
  3. @Produces(value={"text/xml", "application/json"})
  4. public ContactInfo getByEmailAddress(@PathParam(value="emailAddress")
  5. String emailAddress) {
  6. ...
  7. }
  8. @POST
  9. @Consumes(value={"text/xml", "application/json"})
  10. public void addContactInfo(ContactInfo contactInfo) {
  11. ...
  12. }

客户端AngularJS:Accept,Content-Type

例如AngularJS发送请求:

[javascript] view plain copy  print?

  1. $http({method: 'GET', url: '/someUrl'}).
  2. success(function(data, status, headers, config) {
  3. // this callback will be called asynchronously
  4. // when the response is available
  5. }).
  6. error(function(data, status, headers, config) {
  7. // called asynchronously if an error occurs
  8. // or server returns response with an error status.
  9. });

AngularJS Setting HTTP Headers

默认的HTTP头:

The $http service will automatically add certain HTTP headers to all requests. These defaultscan be fully configured by accessing the$httpProvider.defaults.headers configurationobject, which currently contains this default configuration:

  • $httpProvider.defaults.headers.common (headers that are common for all requests):

    • Accept: application/json, text/plain, * / *
    • X-Requested-With: XMLHttpRequest
  • $httpProvider.defaults.headers.post: (header defaults for POST requests)
    • Content-Type: application/json
  • $httpProvider.defaults.headers.put (header defaults for PUT requests)
    • Content-Type: application/json

如何修改HTTP头:

To add or overwrite these defaults, simply add or remove a property from these configuration objects. To add headers for an HTTP method other than POST or PUT, simply add a new objectwith the lowercased HTTP method name as the key, e.g.$httpProvider.defaults.headers.get['My-Header']='value'.

Additionally, the defaults can be set at runtime via the $http.defaults object in the same fashion.

e.g. 修改$httpProvider.defaults.headers(prevent angular.js $http object from sending X-Requested-With header)

[javascript] view plain copy  print?

  1. angular.module('myModule', [])
  2. .config(['$httpProvider', function($httpProvider) {
  3. delete $httpProvider.defaults.headers.common["X-Requested-With"]
  4. }])

e.g. 使用$http.defaults

[javascript] view plain copy  print?

  1. $http({
  2. method: 'POST',
  3. url: url,
  4. headers: {'Content-Type': 'application/x-www-form-urlencoded'}, //headers参数可以设置Accept、Content-Type
  5. }).success(function () {});

Requests与Responses的序列化和反序列化

服务端:实现MessageBodyWriter、MessageBodyReader

JAX-RS 依赖于 MessageBodyReader 和 MessageBodyWriter 的实现来自动完成返回值到响应体的序列化以及请求体到实体参数的反序列化工作,其中,XML 格式的请求/响应数据与 Java 对象的自动绑定依赖于 JAXB 的实现。
用户可以使用 Provider 标注来注册使用自定义的 MessageBodyProvider,如 清单 6 所示,GsonProvider 类使用了 Google Gson 作为 JSON 格式的 MessageBodyProvider 的实现。

[java] view plain copy  print?

  1. @Provider
  2. @Produces("application/json")
  3. @Consumes("application/json")
  4. public class GsonProvider implements MessageBodyWriter<Object>,
  5. MessageBodyReader<Object> {
  6. private final Gson gson;
  7. public GsonProvider() {
  8. gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setDateFormat(
  9. "yyyy-MM-dd").create();
  10. }
  11. public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
  12. MediaType mediaType) {
  13. return true;
  14. }
  15. //MessageBodyReader.readFrom()
  16. public Object readFrom(Class<Object> type, Type genericType,
  17. Annotation[] annotations, MediaType mediaType,
  18. MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
  19. throws IOException, WebApplicationException {
  20. return gson.fromJson(new InputStreamReader(entityStream, "UTF-8"), type);
  21. }
  22. public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
  23. MediaType mediaType) {
  24. return true;
  25. }
  26. public long getSize(Object obj, Class<?> type, Type genericType,
  27. Annotation[] annotations, MediaType mediaType) {
  28. return -1;
  29. }
  30. //MessageBodyWriter.writeTo()
  31. public void writeTo(Object obj, Class<?> type, Type genericType,
  32. Annotation[] annotations, MediaType mediaType,
  33. MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
  34. throws IOException, WebApplicationException {
  35. entityStream.write(gson.toJson(obj, type).getBytes("UTF-8"));
  36. }
  37. }

配置完成后,如何让它生效呢?——可以通过扩展 javax.ws.rs.core.Application 类实现

[java] view plain copy  print?

  1. public class ContactInfoApplicaiton extends Application {
  2. public Set<Class<?>> getClasses() {
  3. Set<Class<?>> classes = new HashSetSet<Class<?>>();
  4. classes.add(ContactsResource.class);
  5. classes.add(ContactInfoWriter.class);
  6. classes.add(ContactInfoReader.class);
  7. }
  8. public SetSet<Object<?>> getSingletons() {
  9. // nothing to do, no singletons
  10. }
  11. }

然后配置web.xml

[html] view plain copy  print?

  1. <web-app id="WebApp_ID" version="2.5">
  2. <servlet>
  3. <servlet-name>ContactInfoServlet</servlet-name>
  4. <servlet-class>com.sample.RESTSystemServlet</servlet-class>
  5. <init-param>
  6. <param-name>javax.ws.rs.Application</param-name>
  7. <param-value>
  8. com.ibm.jaxrs.sample.organization.ContactInfoApplication
  9. </param-value>
  10. </init-param>
  11. </servlet>
  12. <servlet-mapping>
  13. <servlet-name>ContactInfoServlet</servlet-name>
  14. <url-pattern>/*</url-pattern>
  15. </servlet-mapping>
  16. </web-app>

客户端:$httpProvider.defaults.transformRequest/Response

AngularJS Transforming Requests and Responses

Both requests and responses can be transformed using transform functions. By default, Angularapplies these transformations:

Request transformations:

  • If the data property of the request configuration object contains an object,serialize it intoJSON format.

Response transformations:

  • If XSRF prefix is detected, strip it (see Security Considerations section below).
  • If JSON response is detected, deserialize it using a JSON parser.

To globally augment or override the default transforms, modify the $httpProvider.defaults.transformRequest and$httpProvider.defaults.transformResponse properties. These properties are by default an array of transform functions, which allows you topush or unshift a new transformation function into the transformation chain. You can also decide to completely override any default transformations by assigning yourtransformation functions to these properties directly without the array wrapper.

Similarly, to locally override the request/response transforms, augment thetransformRequestand/ortransformResponseproperties of the configuration object passed into$http.

e.g. local配置:在发送请求时设置transformRequest:

[javascript] view plain copy  print?

  1. $http({
  2. method: 'POST',
  3. url: url,
  4. headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  5. transformRequest: function(obj) {
  6. var str = [];
  7. for(var p in obj)
  8. str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
  9. return str.join("&");
  10. },
  11. data: xsrf
  12. }).success(function () {});

e.g. Global配置$httpProvider.defaults.transformRequest

[javascript] view plain copy  print?

  1. var module = angular.module('myApp');
  2. module.config(function ($httpProvider) {
  3. $httpProvider.defaults.transformRequest = function(data){
  4. if (data === undefined) {
  5. return data;
  6. }
  7. return $.param(data);
  8. }
  9. });

RESTEasy

RESTEasy是JBoss提供的JAX-RS 的具体实现。、

web.xml:

[html] view plain copy  print?

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" >
  3. <context-param>
  4. <param-name>resteasy.providers</param-name>
  5. <param-value>
  6. org.jboss.resteasy.plugins.providers.DefaultTextPlain,
  7. org.jboss.resteasy.plugins.providers.ByteArrayProvider,
  8. org.jboss.resteasy.plugins.providers.InputStreamProvider,
  9. org.jboss.resteasy.plugins.providers.ByteArrayProvider,
  10. org.jboss.resteasy.plugins.providers.StringTextStar,
  11. org.jboss.resteasy.plugins.providers.FormUrlEncodedProvider
  12. </param-value>
  13. </context-param>
  14. <context-param>
  15. <param-name>resteasy.scan</param-name>
  16. <param-value>true</param-value>
  17. </context-param>
  18. <context-param>
  19. <param-name>resteasy.servlet.mapping.prefix</param-name>
  20. <param-value>/web</param-value>
  21. </context-param>
  22. <listener>
  23. <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
  24. </listener>
  25. <servlet>
  26. <servlet-name>Resteasy</servlet-name>
  27. <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
  28. </servlet>
  29. <servlet-mapping>
  30. <servlet-name>Resteasy</servlet-name>
  31. <url-pattern>/web/*</url-pattern>
  32. </servlet-mapping>
  33. </web-app>

参考资料

http://liugang594.iteye.com/category/218423

http://www.infoq.com/cn/articles/rest-introduction

http://www.ibm.com/developerworks/cn/web/wa-jaxrs/ 用 Java 技术创建 RESTful Web 服务

http://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/ 使用 JAX-RS 简化 REST 应用开发

http://www.ibm.com/developerworks/cn/webservices/ws-restful/ 基于 REST 的 Web 服务:基础

【REST】REST和JAX-RS相关知识介绍相关推荐

  1. 后端技术:消息队列MQ/JMS/Kafka相关知识介绍

    ?今天给大家分享消息队列MQ/JMS/Kafka相关知识介绍 1.消息队列介绍 首先举个收快递的栗子,传统的收快递,快递小哥把我们的快递送到我们的手里.他需要什么条件嗯? 快递小哥有时间送, 我们有时 ...

  2. pdh光端机相关知识介绍

    目前随着网络信息技术的发展,我们拥有了更加先进的技术运用技巧,其中一个就是pdh光端机的使用.我们自从使用了pdh光端机,对于信息的传输大大的打破了传统的信息传输的缺点.那么,作为一种新生的技术,相信 ...

  3. java窗口三栏布局_移动端的flex三栏布局的相关知识介绍(代码示例)

    本篇文章给大家带来的内容是关于移动端的flex三栏布局的相关知识介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 默认情况下先显示移动端,通过 @media 属性适配屏 ...

  4. 活塞运动c语言编程,动网格的相关知识介绍

    记:在学习使用Fluent的时候,有不少朋友需要使用动网格模型(Dynamic Mesh Model),因此,本版推出这个专题,进行大讨论,使大家在使用动网格时尽量少走弯路,更快更好地掌握:也欢迎使用 ...

  5. LOD技术——定义详解及相关知识介绍

    LOD技术--定义详解及相关知识介绍 LOD技术(Level Of Detail)指用若干不同复杂度的模型来表示同一对象的技术.此技术主要根据视点距离对象位置的变化调用不同复杂度的模型,即在较远时调用 ...

  6. 硬件知识:固态硬盘相关知识介绍

    今天就为大家全面科普一下固态硬盘的相关知识,让大家购买时做到心中有数,按需选择. 首先还是从SSD的结构来说起,SSD最基本的组成部件分为:主控芯片.闪存芯片.固件算法,下面我们分别阐述三者的工作职责 ...

  7. [Redis6]Redis相关知识介绍

    Redis介绍相关知识 端口6379 6379 是 "MERZ " 九宫格输入法对应的数字.Alessia Merz 是一位意大利舞女.女演员. Redis 作者 Antirez ...

  8. 弧形背景html,弧形背景墙—弧形背景墙相关知识介绍

    现在的装修方式真的是很多的,背景墙就是现在一种新型的装修方式,而且就算是一个小小的背景墙,它也是有很多形状的,比如弧形.圆形等.今天小编要给大家介绍的是弧形背景墙的相关知识. 弧形背景墙 弧形背景墙- ...

  9. 介绍php ppt,PHP相关知识介绍.ppt

    [摘要]PHP相关知识的介绍 1.什么是PHP PHP,是英文超级文本预处理语言Hypertext Preprocessor的缩写. PHP 是一种 HTML 内嵌式的语言,是一种在服务器端执行的嵌入 ...

  10. 网络知识:LAN、WAN、WLAN相关知识介绍

    今天给大家介绍一下LAN.WAN.WLAN相关知识,希望对大家能有所帮助! 一.什么是lan.wan和wlan口的区别? 很多朋友对lan口与wan及wlan的用途了解不清楚,尤其是在做路由器桥接时, ...

最新文章

  1. Swift学习:自动引用计数
  2. mxnet与pytorch比较 bn层
  3. python 多进程 循环_python 多进程读取同一个循环处理、可以用multiprocessing
  4. 200个最常见的JAVA面试问题(附答案)
  5. PostgreSQL数据库 OLTP高并发请求性能优化
  6. asp.net MVC留言本示例
  7. cv2.show()cv2.waitKey()cv2.VideoCapture()的使用
  8. LINUX下载编译OpenAL Soft
  9. 功能升级 | Choerodon猪齿鱼“新”知识管理介绍
  10. 川大网页多媒体设计【李天翼班】资料整理
  11. input的失焦事件处理
  12. 新站如何使用好百度站长平台工具
  13. php 极简 新闻,开源极简新闻信息分享工具
  14. WinX菜单是Win8系统开始菜单的下一代
  15. Html页面中直接显示pdf【一行代码实现】
  16. 查看Window系统激活信息
  17. 联想小新锐7000 装win7系统图解
  18. FastAdmin点击输入框, 弹出选择页面, 并把所选的值返回给父窗口
  19. 解决制作系统的U盘被分成两个盘的问题
  20. 乒乓球十一分制比赛规则_乒乓球21分制与11分制

热门文章

  1. android 建数据库 SQLite 存储sd 卡或者内存
  2. CentOS环境下tomcat启动超级慢的解决方案
  3. asp.net %% %#%%=%%@%%$%用法与区别
  4. 数字证书KeyTool使用(第二篇)
  5. 如何在PowerPoint2007制造课件免费ppt模板下载
  6. 科技创业公司的效率工具箱
  7. jQuery源码 Ajax模块分析
  8. 微软独立虚拟机Hyper-V Server 2008
  9. VC基于MSCOMM控件串口通讯
  10. Python-爬取中国天气网天气并通过邮箱定时发送