问题提出
我们知道常规的HTTP方法常用的是GET, POST, PUT, DELETE
。
但是在实际使用中,有些接口明确要求PATCH
方法。其主要用于对模型进行增量修改(全量修改一般用PUT
方法)。
如果我们设计一个HTTP的client,如何实现PATCH
方法的调用,是需要着重考虑的问题。
之前研究过使用开源的hutool工具库hutool-http。其调用方式为
//链式构建请求
String result2 = HttpRequest.patch(url)
.header(Header.USER_AGENT, "Hutool http")//头信息,多个头信息多次调用此方法即可
.form(paramMap)//表单内容
.timeout(20000)//超时,毫秒
.execute().body();
Console.log(result2);
但实际使用中,我发现这样调用PATCH
方法并不能每次都成功(也不是都不能成功)。hutool代码里有明确的处理PATCH
的方法,具体源码如下
这个allowPatch
方法通过反射方式将PATCH
这个方法名称写入到HttpURLConnection
这个类的methods
数组中,这样就保证了客户端能够发起一个PATCH
方法。
遗憾的是,这个代码有时会不生效!通过HttpURLConnection
调用接口时,依然会报如下的错误
更遗憾的是,这个错误的原因未知……
问题解决
虽然原因未知,但可知由于HttpURLConnection
这种原生的类不支持PATCH
方法导致的错误(注意此处并不是说HTTP服务提供者不支持PATCH
方法)。所以绕过以上的类即可,故尝试换做Apache的HttpComponent进行client的构建。
使用HttpComponent组件的方式如下
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPatch patch = new HttpPatch(url);
// 以下的entity对象,为spring提供的HttpEntity
// Set header
entity.getHeaders().forEach((key, value) -> patch.setHeader(key, value.get(0)));
// Set body
patch.setEntity(new StringEntity(entity.getBody(), "UTF-8"));
// Execute
CloseableHttpResponse response = httpClient.execute(patch);
// 将二进制的entity转换为字符串(一般会是json格式)
body = StringUtils.toEncodedString(EntityUtils.toByteArray(response.getEntity()), StandardCharsets.UTF_8);
以上代码测试通过,再也不会出现Invalid HTTP method: PATCH
错误了。
遗留问题
如果能知道hutool的补methods
数组的方式为什么不能生效,就完美了。