您好,登錄后才能下訂單哦!
小編給大家分享一下如何解決RestTemplate請(qǐng)求url中包含百分號(hào)會(huì)被轉(zhuǎn)義成25的問(wèn)題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
最初使用RestTemplate 進(jìn)行遠(yuǎn)程調(diào)用方法如下:
private String getRemoteData(String url) { logger.info("Request URL :" + url + "|"); String resp = rest.getForObject(url, String.class); logger.info("Response result : " + resp.toString()); return resp; }
但發(fā)現(xiàn)請(qǐng)求結(jié)果一直為空。
最后發(fā)現(xiàn)由于我們的業(yè)務(wù)場(chǎng)景中,請(qǐng)求參數(shù)包含中文要求按指定規(guī)則轉(zhuǎn)碼,導(dǎo)致請(qǐng)求url中包含% ,而RestTemplate會(huì)自動(dòng)調(diào)用encode方法進(jìn)行轉(zhuǎn)義,將%轉(zhuǎn)義成了%25 。
自建URI 傳入:
private String getRemoteData(String url) { logger.info("Request URL :" + url + "|"); String resp = null; try { URI uri = new URI(url); resp = rest.getForObject(uri, String.class); } catch (URISyntaxException e) { logger.error("Create URI Exception !"); } logger.info("Response result : " + resp.toString()); return resp; }
發(fā)現(xiàn)一個(gè)關(guān)于HTTP的Get請(qǐng)求的罕見(jiàn)bug。
需要向tigergraph服務(wù)端發(fā)送一個(gè)復(fù)雜的get請(qǐng)求,參數(shù)只有一個(gè),但是參數(shù)的值是一個(gè)復(fù)雜json
服務(wù)端收到的值始終是不正常的值。觀察發(fā)現(xiàn),不正常地方在于服務(wù)端本應(yīng)解析為空格的地方都變成了加號(hào)(+)。
以為是代碼寫得有問(wèn)題,然后使用HTTPclient的原生的方式發(fā)起請(qǐng)求:
public static String doGet(String url) throws Exception{ HttpGet get = new HttpGet(url); return doMethod(get); } private static String doMethod(HttpRequestBase method)throws Exception{ CloseableHttpResponse response = null; CloseableHttpClient client; HttpClientBuilder hcb = HttpClientBuilder.create(); HttpRequestRetryHandler hrrh = new DefaultHttpRequestRetryHandler(); HttpClientBuilder httpClientBuilder = hcb.setRetryHandler(hrrh); client = httpClientBuilder.build(); method.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); method.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON); RequestConfig.Builder confBuilder = RequestConfig.custom(); confBuilder.setConnectTimeout(CONNECT_TIMEOUT); confBuilder.setConnectionRequestTimeout(REQUEST_TIMEOUT); confBuilder.setSocketTimeout(SOCKET_TIMEOUT); RequestConfig config = confBuilder.build(); method.setConfig(config); response = client.execute(method); int code = response.getStatusLine().getStatusCode(); String result = EntityUtils.toString(response.getEntity()); response.close(); client.close(); return result; }
得到結(jié)果還是這個(gè)問(wèn)題,使用Assured測(cè)試工具構(gòu)建http請(qǐng)求也有這問(wèn)題。
后來(lái)仔細(xì)檢查了URLEncode.encode方法和RestTemplate源碼實(shí)現(xiàn)后,發(fā)現(xiàn)是客戶端的轉(zhuǎn)碼協(xié)議和服務(wù)端的解碼協(xié)議不匹配導(dǎo)致。
經(jīng)反復(fù)測(cè)試和嚴(yán)重,這個(gè)問(wèn)題只有參數(shù)中帶有空格時(shí)才會(huì)有,其他字符都不有,比如: / * & 這類特殊字符都沒(méi)這問(wèn)題。
最后的解決方案是替換URL串的轉(zhuǎn)碼后的字符串中的空格為%20,然后使用http client原生的請(qǐng)求方式。
第二個(gè)解決方案是使用RestTemplate的UriComponentsBuilder類,使用(builder.build(false).toUri()獲得URL,參數(shù)必須是false才會(huì)把空格轉(zhuǎn)成%20
/** * urlencode轉(zhuǎn)碼不能隨便用,因?yàn)樗龝?huì)把空格轉(zhuǎn)換成+號(hào),而不是標(biāo)準(zhǔn)的%20字符。 * 對(duì)于spring構(gòu)建的服務(wù)端不會(huì)有這個(gè)問(wèn)題。但我在tiger服務(wù)器上遇到這種問(wèn)題。 * 所以u(píng)rlencode只適用于服務(wù)端支持的協(xié)議是RFC1738 * 如果服務(wù)端只支持RFC 2396標(biāo)準(zhǔn),那么服務(wù)端解碼時(shí),會(huì)把加號(hào)+當(dāng)成保留字符,而不轉(zhuǎn)碼 * */ @Override @SuppressWarnings("all") public <Req, Resp> Resp doGet(String url, Req request, Class<Resp> responseType) throws Exception { UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); Map<String, Object> parameters = (Map<String, Object>)request; for (Map.Entry<String, Object> entry : parameters.entrySet()) { builder.queryParam(entry.getKey(), Objects.toString(entry.getValue(), "")); } return restTemplate.getForObject(builder.build(false).toUri(), responseType); }
根源在于Java語(yǔ)言的URLEncode類只能適用于早期的RFC協(xié)議,通常spring開(kāi)發(fā)的服務(wù)端是兼容這種模式的。
新版的RFC協(xié)議會(huì)把+號(hào)當(dāng)成關(guān)鍵字不再反轉(zhuǎn)成空格,這通常體現(xiàn)在新技術(shù)上,比如目前用的tigergraph圖數(shù)據(jù)庫(kù)就有這情形。
以上是“如何解決RestTemplate請(qǐng)求url中包含百分號(hào)會(huì)被轉(zhuǎn)義成25的問(wèn)題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。