rest:表现层状态转移。java
什么是restful协议?https://en.wikipedia.org/wiki/Representational_state_transfer 使用restful的好处。web
Rest是一种体系结构样式,他定义了一组用于建立web服务的约束。符合REST体系结构风格或RESTful Web服务的Web服务提供Internet上计算机系统之间的互操做性。与rest兼容的web服务容许请求系统经过使用统一的和预约义的无状态操做集来访问和操做web资源的文本表示。其余类型的web服务,如SOAP web服务,公开它们本身的任意操做集。spring
“Web资源”最初在万维网上定义为由url标识的文档或文件。然而,如今它们有了一个更加通用和抽象的定义,它包含了全部能够在web上以任何方式识别、命名、处理或处理的事物或实体。在基于rest的web服务中,对资源URI的请求将经过HTML、XML、JSON或其余格式的有效负载引起响应。响应能够确认对存储的资源进行了一些更改,而且响应能够提供到其余相关资源或资源集合的超文本连接。当使用HTTP时,最多见的操做是GET、POST、PUT、DELETE和其余预约义的CRUD HTTP方法。数据库
经过使用无状态协议和标准操做,REST系统旨在经过重用可管理和更新的组件来实现快速性能、可靠性和增加能力,即便在系统运行时也不影响整个系统。编程
表征状态转移(rest)一词是由Roy Fielding在2000年的博士论文中提出并定义的。从1994年开始,Fielding的论文解释了REST原则,即“HTTP对象模型”,并被用于设计HTTP 1.1和统一资源标识符(Uniform Resource identifier, URI)标准。[4][5][6]这个词是为了唤起的形象设计良好的Web应用程序的行为:它是一个网络的网络资源(虚拟状态机),用户经过应用程序经过选择连接,如/ user /汤姆,和获取或删除等操做(状态转换),致使下一个资源(表明应用程序的下一个状态)传输给用户使用。json
1建筑属性api
REST架构风格的约束影响如下架构属性:浏览器
组件交互中的性能,这是影响用户感知性能和网络效率的主要因素缓存
可伸缩性容许支持大量组件和组件之间的交互。Roy Fielding将REST对可伸缩性的影响描述以下:rest的客户机-服务器关注点分离简化了组件实现,下降了链接器语义的复杂性,提升了性能调优的有效性,并提升了纯服务器组件的可伸缩性。分层系统约束容许中介——代理、网关和防火墙——在通讯的各个点引入,而无需更改组件之间的接口,从而容许它们帮助通讯转换或经过大规模共享缓存提升性能。REST经过将消息约束为自描述的方式实现了中间处理:请求之间的交互是无状态的,标准方法和媒体类型用于指示语义和交换信息,响应显式地指示可缓存性。安全
统一接口的简单性;
组件的可修改性以知足不断变化的需求(甚至在应用程序运行时);
服务代理之间组件间通讯的可见性;
利用数据移动程序代码实现组件的可移植性;
在组件、链接器或数据中存在故障时,在系统级别对故障的抵抗的可靠性。
2体系结构约束
六个指导约束定义了一个RESTful系统。这些约束限制了服务器处理和响应客户机请求的方式,所以,经过在这些约束中操做,服务能够得到理想的非功能属性,如性能、可伸缩性、简单性、可修改性、可见性、可移植性和可靠性。若是服务违反了任何须需的约束,就不能认为它是RESTful的。
形式REST约束以下:
客户机-服务器体系结构
客户机-服务器约束背后的原则是关注点分离。将用户界面关注与数据存储关注分离能够提升用户界面跨多个平台的可移植性。它还经过简化服务器组件来提升可伸缩性。然而,对Web来讲最重要的多是分离容许组件独立地演进,从而支持多个组织领域的internet规模需求
无国籍(无状态协议)
客户机-服务器通讯受到请求之间服务器上没有存储客户机上下文的约束。来自任何客户机的每一个请求都包含服务请求所需的全部信息,会话状态保存在客户机中。服务器能够将会话状态转移到另外一个服务(如数据库),以便在一段时间内保持持久状态并容许身份验证。客户端在准备转换到新状态时开始发送请求。当一个或多个请求未完成时,客户端被认为处于过渡状态。每一个应用程序状态的表示都包含可在下次客户端选择发起新的状态转换时使用的连接。
缓存能力
在万维网上,客户机和中介体能够缓存响应。所以,响应必须隐式或显式地将本身定义为可缓存的或不可缓存的,以防止客户机在响应进一步请求时获取陈旧或不合适的数据。管理良好的缓存部分或彻底消除了一些客户机-服务器交互,进一步提升了可伸缩性和性能。
可缓存:
HTTP状态码(org.springframework.http.HttpStatus)
200:HttpStatus#ok
304:HttpStatus#NOT_MODIFIED 第一次完整请求,获取响应头(200),body直接获取,第二次请求,只读取头信息,响应头(304),客户端(浏览器)取上次body结果。
400:HttpStatus#BAD_REQUEST
....
响应:
响应头(Headers)
元信息(Meta-Data)
Accept-Language->Locale
Connection->Keep-Alive
实现多值Map:MutiValueMap
key:value=1:n
name:value=1:n
响应体
业务信息(Business Data)
Body:HTTP实体、REST
@ResponseBody
HttpEntity.body属性(泛型结构)
Payload:消息JMS、事件、SOAP
分层系统
客户端一般没法分辨它是直接链接到终端服务器,仍是一路链接到中介。中介服务器能够经过启用负载平衡和提供共享缓存来提升系统的可伸缩性。它们还能够执行安全策略。
按需编码(可选)
参见:客户端脚本
服务器能够经过传输可执行代码临时扩展或定制客户机的功能。例如,编译组件(如Java applet)和客户端脚本(如JavaScript)。
3统一的接口
统一接口约束是任何REST服务设计的基础。它简化和解耦了体系结构,使每一个部分可以独立发展。这个统一接口的四个约束条件是:
请求中的资源标识:即自定义消息
在请求中标识单个资源,例如在基于web的REST系统中使用uri。资源自己在概念上与返回给客户机的表示是分开的。例如,服务器能够从数据库中以HTML、XML或json的形式发送数据——这些都不是服务器的内部表示。
经过表示操做资源----http动词
当客户机持有资源的表示形式(包括附加的任何元数据)时,它有足够的信息来修改或删除资源。
自描述信息
每一个消息都包含足够的信息来描述如何处理消息。例如,能够经过媒体类型指定要调用的解析器
注解驱动
@RequestBody
JSON-> MappingJackson2HttpMessageConverter
@ResponseBody
JSON->MappingJackson2HttpMessageConverter
接口编程
ResponseEntity extends HttpEntity
RequestEntity extends HttpEntity
超媒体做为应用程序状态(HATEOAS)的引擎
访问了REST应用程序的初始URI(相似于人工Web用户访问Web站点的主页)以后,REST客户机应该可以动态地使用服务器提供的连接来发现它所需的全部可用操做和资源。随着访问的继续,服务器将使用文本进行响应,其中包括指向当前可用的其余操做的超连接。客户端不须要硬编码有关REST服务的结构或动态的信息。
应用于Web服务
遵循REST体系结构约束的Web服务api称为RESTful api。基于http的RESTful api的定义以下
一个基本URL,例如http://api.example.com/resources;
定义状态转换数据元素(例如,Atom、微格式、应用程序/vnd)的媒体类型。当前表示告诉客户端如何组合转换到全部下一个可用应用程序状态的请求。这能够像URL同样简单,也能够像Java applet同样复杂
标准HTTP方法(例如,选项、GET、PUT、POST和DELETE)
URL和HTTP方法之间的关系
下表显示了在RESTful API中一般如何使用HTTP方法:
HTTP方法
Get、put、patch、Post、delete
GET方法是一种安全的方法(或无效),这意味着调用它不会产生反作用:检索或访问记录不会改变它。PUT和DELETE方法是等幂的,这意味着不管重复请求多少次,API公开的系统状态都是不变的。
与基于soap的Web服务不一样,RESTful Web api没有“官方”标准。这是由于REST是一种体系结构风格,而SOAP是一种协议。REST自己不是标准,可是RESTful实现使用了标准,例如HTTP、URI、JSON和XML。许多开发人员还将他们的api描述为RESTful,尽管这些api实际上并无实现上面描述的全部架构约束(尤为是统一接口约束)
资源定位-URI
资源操做-HTTP动词
GET
@GetMapping
注解属性别名和覆盖:在Spring framework4.2中引入,Spring Boot1.3才能使用,Spring Boot加以发展,能够看一下AnnotatedElementUtils.getMergedAnnotationAttributes
根据这个,能够本身实现相似的注解,好比:
PUT
@PutMapping
POST
@PostMapping
@PostMapping是注解,@RequestMapping是@PostMapping的注解:
@RequestMapping是@PostMapping的元注解
@RequestMapping元标注了@PostMapping
@AliasFor只能标注在目标注解的属性,所annotation()的注解必须是元注解,该注解attribute必须是是元注解的属性。
PATCH
@PatchMapping
限制,在Servlet API中并无规定PATCH方法,Spring Web对其作了扩展。
javax.servlet.http.HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }
DELETE
@DeleteMapping
根据别名覆盖和这几个注解,咱们能够尝试写一个组合注解,把2个注解的功能结合起来,好比:
以上还能够对事务起个别名: