在RESTful风格的API中。PUT/PATCH方法一般用于更新数据。在项目的代码中,使用的是HttpClient 4.5,是这样写的:

protected JSONObject doHttpUriRequest(HttpUriRequest httpUriRequest) {
JSONObject result = null; HttpClient httpClient = HttpClients.createDefault();
try {
HttpResponse httpResponse = httpClient.execute(httpUriRequest);
StatusLine responseStatusLine = httpResponse.getStatusLine(); int statusCode = responseStatusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity responseEntity = httpResponse.getEntity(); String jsonString = EntityUtils.toString(responseEntity, CHARACTER_SET);
result = new JSONObject(jsonString); EntityUtils.consume(responseEntity);
} else {
// error handling
}
} catch (IOException e) {
e.printStackTrace();
return onLocalError(e);
} return result;
} protected JSONObject doHttpPatch(String uri, Map<String, String> params) {
JSONObject result = null; HttpPatch httpPatch = new HttpPatch(uri);
List<NameValuePair> nvps = constructNvps(params); // constructing name-value pair try {
httpPatch.setEntity(new UrlEncodedFormEntity(nvps, CHARACTER_SET));
result = doHttpUriRequest(httpPatch);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return onLocalError(e);
} return result;
}

当中doHttpUriRequest()是一个处理发送请求的工具函数。doHttpPatch()是详细处理数据的函数。

可见写法和一个普通的POST请求差点儿相同,仅仅是将HttpPost换成HttpPatch。

但是在server端,比方在params中有一个參数叫key。值是value,在Controller里面,能识别到这是一个PATCH方法,但是key的值是null。就是Servlet不能从form里面获取參数。

Google查了一下原因,大体是说PATCH这种方法非常新,就算到Tomcat 7.0.39也都不支持。

那怎么破呢?有两个办法:

1. 用URI来请求

既然不能使用form来获取參数,那就写在URI的尾巴吧:

protected JSONObject doHttpPatchWithURI(String uri, Map<String, String> params) {
JSONObject result = null;
URIBuilder uriBuilder = new URIBuilder();
uriBuilder.setPath(uri);
uriBuilder.setParameters(constructNvps(params)); try {
URI builtUri = uriBuilder.build();
HttpPatch httpPatch = new HttpPatch(builtUri);
result = doHttpUriRequest(httpPatch);
} catch (URISyntaxException e) {
e.printStackTrace();
return onLocalError(e);
} return result;
}

使用了这样的做法,servlet能够获得參数了。

这种方法有一个问题。就是即使key是null值,在URI的參数也会带上。在Servlet里面接收,key的值会变成”“(空字符串)。这样在RESTful风格API里面会有歧义:到底是不更新,还是更新成空字符串呢?

2. 在web.xml中增加一个filter

还有一种做法是保持使用上面POST风格的方法,在web.xml中增加一个filter:

<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<servlet-name>springWebMvcDispatcher</servlet-name>
</filter-mapping>

当中springWebMvcDispatcher是servlet的名字。

Filter的工作是从request body的form data里面读取数据,然后包装成一个ServletRequest,使得ServletRequest.getParameter*()之类的方法能够读取到数据。

參考文档:

http://stackoverflow.com/questions/20370927/patch-method-in-tomcat-with-spring-mvc

Tomcat + Spring MVC + HttpClient:怎样使用PUT和PATCH方法传递数据的更多相关文章

  1. 【Spring学习笔记-MVC-5】利用spring MVC框架,实现ajax异步请求以及json数据的返回

    作者:ssslinppp      时间:2015年5月26日 15:32:51 1. 摘要 本文讲解如何利用spring MVC框架,实现ajax异步请求以及json数据的返回. Spring MV ...

  2. 【问题】Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数

    [问题]Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数. [解决]直接对变量加引号,如: <button onclick="deleteProduct('@ ...

  3. MVC学习系列3--怎么从控制器向视图传递数据

    在MVC中,从控制器到视图,传递数据,可以使用 ViewData 和 ViewBag:同样从视图到控制器,传递数据,可以使用Post,QueryString,或者隐藏域:最后从控制器到控制器,传递数据 ...

  4. Spring MVC 学习总结(三)——请求处理方法Action详解

    Spring MVC中每个控制器中可以定义多个请求处理方法,我们把这种请求处理方法简称为Action,每个请求处理方法可以有多个不同的参数,以及一个多种类型的返回结果. 一.Action参数类型 如果 ...

  5. Spring MVC中处理静态资源的多种方法

    处理静态资源,我想这可能是框架搭建完成之后Web开发的”头等大事“了. 因为一个网站的显示肯定会依赖各种资源:脚本.图片等,那么问题来了,如何在页面中请求这些静态资源呢? 还记得Spring MVC中 ...

  6. spring mvc 中文乱码 post与get的方法解决

    spring mvc表单提交中文参数乱码问题 今天测试spring mvc  ,中文乱码,在web.xml中加上 <filter> <filter-name>encodingF ...

  7. Spring MVC 中获取session的几种方法

    Spring MVC 中使用session是一种常见的操作,但是大家上网搜索一下可以看到获取session的方式方法五花八门,最近,自己终结了一下,将获取session的方法记录下来,以便大家共同学习 ...

  8. spring MVC 返回值信息和ResponseBody的响应json数据

    spring mvc的界面返回: 如果我们定义的返回类型是String 那么我们返回的时候直接写入 我们的界面的名字就可以了  springmvc会自动去找到我们的界面,如果是void类型的返回那么 ...

  9. Spring MVC与html页面的交互(以传递json数据为例)

    一.导入相jar包 主要包括spring相关jar包和fastjson jar包,具体步骤略. 二.配置相关文件 1.配置web.xml文件 <?xml version="1.0&qu ...

随机推荐

  1. 【linux高级程序设计】(第十二章)Linux多线程编程 4

    读写锁 书上有读者写者的代码,我实在是懒得实现一遍了.跟之前的代码差不多. 多线程异步信号处理 int pthread_kill (pthread_t __threadid, int __signo) ...

  2. js 抽奖小案例

    Luck Draw 在线演示:九宫格抽奖 对九宫格形式的抽奖页面进行了一些简单封装.以后有机会再更新其他形式的抽奖.

  3. Codeforces 897 A.Scarborough Fair-字符替换

      A. Scarborough Fair   time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  4. Spring Cloud底层原理(转载 石杉的架构笔记)

    拜托!面试请不要再问我Spring Cloud底层原理 原创: 中华石杉 石杉的架构笔记   目录 一.业务场景介绍 二.Spring Cloud核心组件:Eureka 三.Spring Cloud核 ...

  5. 【高精度】高精度数除以低精度数I

    问题 G: [高精度]高精度数除以低精度数I 时间限制: 1 Sec  内存限制: 512 MB提交: 173  解决: 71[提交] [状态] [讨论版] [命题人:] 题目描述 修罗王聚集了庞大的 ...

  6. 为什么我不使用Kubernetes的Ingress

    为什么我不使用Kubernetes的Ingress 很不幸,据我所知Kubernetes的文档不是很完美,这就是为什么有很多同学在使用它的时候会遇到很多的坑,Ingress这个组件就是这些坑中的一个. ...

  7. Java:网络编程值TCP的使用

    演示TCP传输   1.Tcp分客户端和服务端 2.客服端对应的对象是scoket    服务端对应的对象是serverscoket   客户端: 通过查阅scoket对象,发现在建立对象时,就可以连 ...

  8. 关于BufferedInputStream和BufferedOutputStream的实现原理的理解

    在介绍FileInputStream和FileOutputStream的例子中,使用了一个byte数组来作为数据读入的缓冲区,以文件存取为例,硬盘存取的速度远低于内存中的数据存取速度.为了减少对硬盘的 ...

  9. ruby ide

    uby 是个动态面向对象.通用的编程语言.它支持多种编程范式,包括面向功能和面向对象.同时它也包括一个动态类型系统和自动内存管理. 编辑器和集成开发环境(IDE)有些不同,编辑器是用来添加,编辑,查看 ...

  10. LeetCode 14: Longest Common Prefix

    Longest Common Prefix Write a function to find the longest common prefix string amongst an array of ...