PATCH METHOD使用

背景

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

语义

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

和PUT对比

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

实现和支持

  • 支持:

    • Apache HttpComponents HttpClient version 4.2 or later 支持了 PATCH
    • Spring 3.2 开始支持 PATCH 方法,但要选对部署的容器
    • JBoss Netty 支持 PATCH
  • 不支持:

    • 目前 JDK7 的 HttpURLConnection 未实现 PATCH
    • TOMCAT 7 也不行
    • PlayFramework 2 也不支持

在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为application/json
设置contentType
  • 在body中使用JSON传参
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

服务端代码:

  • web.xml中增加filter
<!-- 隐藏方法拦截器 -->
<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>
  • controller代码
 /**
  * 更新 (客户端上送部分数据)
  * patch 传递参数的方法:
  *  1) HiddenHttpMethodFilter + 额外字段_method
  */
 @RequestMapping(path = "{id}", method = RequestMethod.PATCH)
 @ResponseBody
 public String patch(@PathVariable String id, UserInfo userInfo) {}
4. 使用HttpPutFormContenrFilter

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

没有_method字段

服务端代码:

  • web.xml中增加filter
    <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>
  • controller代码
 /**
  * 更新 (客户端上送部分数据)
  * patch 传递参数的方法:
  *  1) HttpPutFormContentFilter
  */
 @RequestMapping(path = "{id}", method = RequestMethod.PATCH)
 @ResponseBody
 public String patch(@PathVariable String id, UserInfo userInfo) {}

注:

  • ①: 八个动作分别为: OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE、CONNECT
  • ②: 2010年3月份才成为正式方法,见“RFC 5789
  • ③:就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对,比如,name=Java&age = 23
  • ④: HiddenHttpMethodFilter和HttpPutFormContenrFilter的区别:

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

HiddenHttpMethodFilter

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

HiddenHttpMethodFilter

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容