程序员

PATCH METHOD使用

2017-07-03  本文已影响0人  老夫乃野马只待皮鞭抽

背景

目前广泛使用的HTTP/1.1中定义了八个基本动作①,而PATCH属于扩展动作出现较晚②,很多容器或者库类的API都没有支持。所以我们在处理PATCH方法时常常需要使用一些额外的方法。

语义

用于更新资源的部分内容。例如,更新用户信息中的姓名字段。

和PUT对比

  1. 当资源存在时:
    • PATCH 用于资源的部分内容的更新
    • PUT 用于更新某个资源较完整的内容
  2. 当资源不存在时
    • PATCH 可能会去创建一个新的资源,像是 saveOrUpdate
    • PUT 只对已有资源进行更新操作,所以是 update 操作

实现和支持

在Spring中使用PATCH

背景

PATCH方法默认是以x-www-form-urlencoded③的contentType来发送信息,并且信息内容是放在request的body里。而
Springmvc在解析参数的时候使用的解析器是ServletModelAttributeMethodProcessor,该解析器不支持PATCH,当使用getParameterMap()获取body内容的时候,获取不到信息。

解决办法

1.使用查询字符串传参:

使用POSTMAN模拟客户端发起请求:


查询字符串传参

服务端接收参数:

 /**
  * 更新 (客户端上送部分数据)
  * patch 传递参数的方法:
  *  1) 使用查询字符串
  */
 @RequestMapping(path = "{id}", method = RequestMethod.PATCH)
 @ResponseBody
 public String patch(@PathVariable String id, UserInfo userInfo) {}
2.使用@RequestBody + JSON :

Spring中使用@RequestBody来绑定数据时,使用的是RequestResponseBodyMethodProcessor来解析参数,该解析器可以将json格式的内容装载到pojo里。而@RequestBody只支持以下几种contentType:application/jsonapplication/hal+jsonapplication/pathc+jsonapplication/merge-pathc+json。示例如下:

1)使用PostMan测试

使用POSTMAN模拟客户端发起请求:

设置contentType JSON数据

服务端接收请求:

/**
 * 更新 (客户端上送部分数据)
 * patch 传递参数的方法:
 *  1) @RequestBody + JSON
 */
@RequestMapping(path = "{id}", method = RequestMethod.PATCH)
@ResponseBody
public String patch(@PathVariable String id, @RequestBody UserInfo userInfo) {}
2)使用ajax作为客户端的代码
$.ajax({
    url: 'http://localhost/v1/users/1',
    type: 'PATCH',
    contextType: 'application/json',
    data: JSON.stringify({
        name: '张三',
        age: '18'
    })
})
3. 使用表单隐藏字段(_method) + HiddenHttpMethodFilter

使用POSTMAN模拟客户端发起请求:

隐藏字段:_method

服务端代码:

<!-- 隐藏方法拦截器 -->
<filter>
    <filter-name>HttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
 /**
  * 更新 (客户端上送部分数据)
  * patch 传递参数的方法:
  *  1) HiddenHttpMethodFilter + 额外字段_method
  */
 @RequestMapping(path = "{id}", method = RequestMethod.PATCH)
 @ResponseBody
 public String patch(@PathVariable String id, UserInfo userInfo) {}
4. 使用HttpPutFormContenrFilter

使用POSTMAN模拟客户端发起请求:

没有_method字段

服务端代码:

    <filter>
        <filter-name>HttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 /**
  * 更新 (客户端上送部分数据)
  * patch 传递参数的方法:
  *  1) HttpPutFormContentFilter
  */
 @RequestMapping(path = "{id}", method = RequestMethod.PATCH)
 @ResponseBody
 public String patch(@PathVariable String id, UserInfo userInfo) {}

注:

HttpPutFormContenrFilter只能处理PUT和PATCH动作。其内部实现是获取以上两种请求的表单参数后,封装一个新的request包装类:

HiddenHttpMethodFilter

HiddenHttpMethodFilter除了PUT和PATCH还能处理DELETE等动作。但是必须增加一个隐藏参数_method,增加了客户端代码的耦合:

HiddenHttpMethodFilter
上一篇下一篇

猜你喜欢

热点阅读