当前位置: 代码迷 >> VC/MFC >> Tomcat + Spring MVC + HttpClient:怎么使用PUT和PATCH方法传递数据
  详细解决方案

Tomcat + Spring MVC + HttpClient:怎么使用PUT和PATCH方法传递数据

热度:516   发布时间:2016-05-02 03:57:31.0
Tomcat + Spring MVC + HttpClient:如何使用PUT和PATCH方法传递数据

在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

版权声明:本文为博主原创文章,未经博主允许不得转载。