問(wèn)題提出
我們知道常規(guī)的HTTP方法常用的是GET, POST, PUT, DELETE。
但是在實(shí)際使用中,有些接口明確要求PATCH方法。其主要用于對(duì)模型進(jìn)行增量修改(全量修改一般用PUT方法)。
如果我們?cè)O(shè)計(jì)一個(gè)HTTP的client,如何實(shí)現(xiàn)PATCH方法的調(diào)用,是需要著重考慮的問(wèn)題。
之前研究過(guò)使用開源的hutool工具庫(kù)hutool-http。其調(diào)用方式為
//鏈?zhǔn)綐?gòu)建請(qǐng)求
String result2 = HttpRequest.patch(url)
.header(Header.USER_AGENT, "Hutool http")//頭信息,多個(gè)頭信息多次調(diào)用此方法即可
.form(paramMap)//表單內(nèi)容
.timeout(20000)//超時(shí),毫秒
.execute().body();
Console.log(result2);
但實(shí)際使用中,我發(fā)現(xiàn)這樣調(diào)用PATCH方法并不能每次都成功(也不是都不能成功)。hutool代碼里有明確的處理PATCH的方法,具體源碼如下

這個(gè)allowPatch方法通過(guò)反射方式將PATCH這個(gè)方法名稱寫入到HttpURLConnection這個(gè)類的methods數(shù)組中,這樣就保證了客戶端能夠發(fā)起一個(gè)PATCH方法。
遺憾的是,這個(gè)代碼有時(shí)會(huì)不生效!通過(guò)HttpURLConnection調(diào)用接口時(shí),依然會(huì)報(bào)如下的錯(cuò)誤

更遺憾的是,這個(gè)錯(cuò)誤的原因未知……
問(wèn)題解決
雖然原因未知,但可知由于HttpURLConnection這種原生的類不支持PATCH方法導(dǎo)致的錯(cuò)誤(注意此處并不是說(shuō)HTTP服務(wù)提供者不支持PATCH方法)。所以繞過(guò)以上的類即可,故嘗試換做Apache的HttpComponent進(jìn)行client的構(gòu)建。
使用HttpComponent組件的方式如下
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPatch patch = new HttpPatch(url);
// 以下的entity對(duì)象,為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);
// 將二進(jìn)制的entity轉(zhuǎn)換為字符串(一般會(huì)是json格式)
body = StringUtils.toEncodedString(EntityUtils.toByteArray(response.getEntity()), StandardCharsets.UTF_8);
以上代碼測(cè)試通過(guò),再也不會(huì)出現(xiàn)Invalid HTTP method: PATCH錯(cuò)誤了。
遺留問(wèn)題
如果能知道hutool的補(bǔ)methods數(shù)組的方式為什么不能生效,就完美了。