最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決RestTemplate 請(qǐng)求url中包含百分號(hào) 會(huì)被轉(zhuǎn)義成25的問題

 更新時(shí)間:2021年10月28日 11:16:11   作者:toneylyx  
這篇文章主要介紹了解決RestTemplate 請(qǐng)求url中包含百分號(hào) 會(huì)被轉(zhuǎn)義成25的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。

RestTemplate 請(qǐng)求url中包含百分號(hào) 會(huì)被轉(zhuǎn)義成25

最初使用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;
 }

RestTemplate轉(zhuǎn)碼bug

發(fā)現(xiàn)一個(gè)關(guān)于HTTP的Get請(qǐng)求的罕見bug。

轉(zhuǎn)碼問題的背景

需要向tigergraph服務(wù)端發(fā)送一個(gè)復(fù)雜的get請(qǐng)求,參數(shù)只有一個(gè),但是參數(shù)的值是一個(gè)復(fù)雜json

服務(wù)端收到的值始終是不正常的值。觀察發(fā)現(xiàn),不正常地方在于服務(wù)端本應(yīng)解析為空格的地方都變成了加號(hào)(+)。

以為是代碼寫得有問題,然后使用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è)問題,使用Assured測(cè)試工具構(gòu)建http請(qǐng)求也有這問題。

結(jié)論

后來仔細(xì)檢查了URLEncode.encode方法和RestTemplate源碼實(shí)現(xiàn)后,發(fā)現(xiàn)是客戶端的轉(zhuǎn)碼協(xié)議和服務(wù)端的解碼協(xié)議不匹配導(dǎo)致。

經(jīng)反復(fù)測(cè)試和嚴(yán)重,這個(gè)問題只有參數(shù)中帶有空格時(shí)才會(huì)有,其他字符都不有,比如: / * & 這類特殊字符都沒這問題。

最后的解決方案是替換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è)問題。但我在tiger服務(wù)器上遇到這種問題。 * 所以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);
    }

為什么會(huì)有這個(gè)問題?

根源在于Java語言的URLEncode類只能適用于早期的RFC協(xié)議,通常spring開發(fā)的服務(wù)端是兼容這種模式的。

新版的RFC協(xié)議會(huì)把+號(hào)當(dāng)成關(guān)鍵字不再反轉(zhuǎn)成空格,這通常體現(xiàn)在新技術(shù)上,比如目前用的tigergraph圖數(shù)據(jù)庫就有這情形。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Boot集群管理工具KafkaAdminClient使用方法解析

    Spring Boot集群管理工具KafkaAdminClient使用方法解析

    這篇文章主要介紹了Spring Boot集群管理工具KafkaAdminClient使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java小程序計(jì)算圓周率代碼

    Java小程序計(jì)算圓周率代碼

    這篇文章主要介紹了Java小程序計(jì)算圓周率代碼,有兩種實(shí)現(xiàn)方法,喜歡的朋友可以參考下。
    2017-09-09
  • java爬蟲之使用HttpClient模擬瀏覽器發(fā)送請(qǐng)求方法詳解

    java爬蟲之使用HttpClient模擬瀏覽器發(fā)送請(qǐng)求方法詳解

    這篇文章主要介紹了java爬蟲之使用HttpClient模擬瀏覽器發(fā)送請(qǐng)求方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java中的CyclicBarrier、CountDownLatch和Semaphore的具體使用

    Java中的CyclicBarrier、CountDownLatch和Semaphore的具體使用

    本文主要介紹了Java中的CyclicBarrier、CountDownLatch和Semaphore的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn)

    SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn)

    Spring Cloud Gateway 作為網(wǎng)關(guān)層,承擔(dān)著請(qǐng)求轉(zhuǎn)發(fā)、權(quán)限校驗(yàn)等重要職責(zé),本文主要介紹了SpringCloud Gateway 權(quán)限認(rèn)證的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • Java使用Knife4j優(yōu)化Swagger接口文檔的操作步驟

    Java使用Knife4j優(yōu)化Swagger接口文檔的操作步驟

    在現(xiàn)代微服務(wù)開發(fā)中,接口文檔的質(zhì)量直接影響了前后端協(xié)作效率,Swagger 作為一個(gè)主流的接口文檔工具,雖然功能強(qiáng)大,但其默認(rèn)界面和部分功能在實(shí)際使用中略顯不足,而 Knife4j 的出現(xiàn)為我們提供了一種增強(qiáng)的選擇,本篇文章將詳細(xì)介紹如何在項(xiàng)目中集成和使用 Knife4j
    2024-12-12
  • SpringBoot控制配置類加載順序方式

    SpringBoot控制配置類加載順序方式

    這篇文章主要介紹了SpringBoot控制配置類加載順序方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Java實(shí)現(xiàn)按照大小寫字母順序排序的方法

    Java實(shí)現(xiàn)按照大小寫字母順序排序的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)按照大小寫字母順序排序的方法,涉及java數(shù)組遍歷、編碼轉(zhuǎn)換、判斷等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • java實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng)

    java實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • MybatisPlus實(shí)現(xiàn)邏輯刪除功能

    MybatisPlus實(shí)現(xiàn)邏輯刪除功能

    這篇文章主要介紹了MybatisPlus實(shí)現(xiàn)邏輯刪除功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論

漳平市| 合阳县| 辽宁省| 涿州市| 宁都县| 六枝特区| 潍坊市| 沐川县| 金昌市| 鸡西市| 淮南市| 夏邑县| 湖北省| 光山县| 仪征市| 界首市| 瓮安县| 施甸县| 龙门县| 长汀县| 阿尔山市| 白城市| 扎鲁特旗| 朝阳区| 开江县| 玉环县| 满洲里市| 五家渠市| 嘉峪关市| 萨嘎县| 县级市| 荣成市| 漠河县| 镇康县| 辽阳县| 盈江县| 临安市| 乌兰县| 兰西县| 和平县| 通榆县|