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

restemplate請求亂碼之content-encoding=“gzip“示例詳解

 更新時間:2024年03月29日 11:18:36   作者:一名技術(shù)極客  
RestTemplate從Spring3.0開始支持的一個HTTP請求工具,它提供了常見的REST請求方案的模板,及一些通用的請求執(zhí)行方法 exchange 以及 execute,接下來通過本文給大家介紹restemplate請求亂碼之content-encoding=“gzip“,需要的朋友可以參考下

什么是 RestTemplate

  RestTemplate 是從 Spring3.0 開始支持的一個 HTTP 請求工具,它提供了常見的 REST請求方案的模板,例如 GET 請求、POST 請求、PUT 請求、DELETE 請求以及一些通用的請求執(zhí)行方法 exchange 以及 execute。RestTemplate 繼承自 InterceptingHttpAccessor 并且實現(xiàn)了 RestOperations 接口,其中 RestOptions 接口定義了基本的 RESTful 操作,這些操作在 RestTemplate 中都得到了實現(xiàn)。

restemplate請求亂碼之content-encoding="gzip"

今天有一個通過Restemplate請求一個天氣API,發(fā)現(xiàn)其Body數(shù)據(jù)是亂碼,同事處理了好久,然并卵,經(jīng)檢查后,發(fā)現(xiàn)頭部信息出了問題。

content-encoding="gzip"
content-type="application/json;charset=UTF-8"

返回值是UTF-8,Restemplate設置的也是UTF-8。在翻看其他博客,發(fā)現(xiàn)問題原因是http存在一個壓縮格式:Gzip。

Gzip是一個壓縮算法,當請求數(shù)據(jù)或返回數(shù)據(jù)體積過大,為減少網(wǎng)絡負載壓力而使用的壓縮算法。通常在服務器端使用,客戶端為獲得原始數(shù)據(jù)需通過Gzip解壓。

響應頭中的gzip

Content-Encoding

是一個實體消息首部,用于對特定媒體類型的數(shù)據(jù)進行壓縮。當這個首部出現(xiàn)的時候,它的值表示消息主體進行了何種方式的內(nèi)容編碼轉(zhuǎn)換。這個消息首部用來告知客戶端應該怎樣解碼才能獲取在 Content-Type 中標示的媒體類型內(nèi)容。

一般建議對數(shù)據(jù)盡可能地進行壓縮,因此才有了這個消息首部的出現(xiàn)。

注:客戶端和服務器都可以使用,表示body中的數(shù)據(jù)采用了什么編碼(壓縮算法)

Accept-Encoding

HTTP 請求頭 Accept-Encoding 會將客戶端能夠理解的內(nèi)容編碼方式——通常是某種壓縮算法——進行通知(給服務端)。通過內(nèi)容協(xié)商的方式,服務端會選擇一個客戶端提議的方式,使用并在響應頭 Content-Encoding 中通知客戶端該選擇。

注:一般是客戶端使用,表示給服務器說明,客戶端支持的壓縮算法列表。服務從中選擇一個對響應體進行壓縮。

/**
     * @Title: getClimateByRequst
     * @Description: ( 通過request 獲取天氣信息)
     * @Author:lijie
     * @since 2021/11/9 14:05
     * @Version:1.1.0
     * @return:   climate:封裝的天氣結(jié)果類
     */
public Result<Climate> getClimateByRequst(HttpServletRequest request) {
    Result<Climate> result=new Result<>();
    try{
        //通過request請求獲得ip地址
        String ip = WebUtils.getIpByRequset(request);
        //通過ip獲得大致定位
        Result<Map<String, Object>> locationByIP = this.getLocationByIP(ip);
        if(locationByIP!=null&&locationByIP.isSuccess()){
            Map<String, Object> data = locationByIP.getData();
            String url=""http://請求的url地址
            if(MapUtils.isNotEmpty(data)){
                String jd = MapUtils.getString(data, "jd");//精度
                String wd = MapUtils.getString(data, "wd");//緯度
                HttpHeaders httpHeaders = new HttpHeaders();
                // Accept 表示客戶端支持什么格式的響應體
                httpHeaders.set("contentType", "application/json;charset=UTF-8");
                // Accept-Encoding 頭,表示客戶端可以接收gzip格式的壓縮
                httpHeaders.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
                //發(fā)送請求 
                ResponseEntity<byte[]> forEntity = restTemplate.exchange
                        (url, HttpMethod.GET, new HttpEntity<>(httpHeaders), byte[].class);
                if(forEntity.getStatusCode()== HttpStatus.OK){
                    // 獲取服務器響應體編碼
                    String contentEncoding = forEntity.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
                    if ("gzip".equals(contentEncoding)) { // 是gzip編碼
                        // gzip解壓服務器的Body響應體
                        byte[] weatherData = WebUtils.unGZip(
                                new ByteArrayInputStream(Objects.requireNonNull(forEntity.getBody())));
                        String weatherJson = new String(weatherData, StandardCharsets.UTF_8);
                        Climate climate = JSONObject.parseObject(weatherJson, Climate.class);
                        if(climate!=null){
                            result.setSuccess();
                            result.setData(climate);
                        }
                    } else {
                        // todo 其他的編碼
                        result.setErrored("和風API響應值編碼不是Gzip,請聯(lián)系我,謝謝");
                    }
                }else{
                    result.setErrored("和風API響應出錯了");
                }
            }
        }
    }catch (Exception e){
        result.setErrored("天氣獲取出錯了");
    }
    return result;
}
/**
	 * Gzip解壓縮
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	public static byte[] unGZip(InputStream inputStream) throws IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try (GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
			byte[] buf = new byte[4096];
			int len = -1;
			while ((len = gzipInputStream.read(buf, 0, buf.length)) != -1) {
				byteArrayOutputStream.write(buf, 0, len);
			}
			return byteArrayOutputStream.toByteArray();
		} finally {
			byteArrayOutputStream.close();
		}
	}
/**
	 * Gzip壓縮數(shù)據(jù)
	 * @param data
	 * @return
	 * @throws IOException
	 */
	public static byte[] gZip(byte[] data) throws IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
			gzipOutputStream.write(data);
			gzipOutputStream.finish();
			return byteArrayOutputStream.toByteArray();
		}
	}

SpringBoot的響應體壓縮配置

實際上,并不需要自己手動去寫這種響應體的壓縮代碼。springboot提供了相關的配置。只針對響應壓縮

server:
  compression:
    # 開啟響應壓縮
    enabled: true
  # 支持的壓縮類型
  mime-types: 
    - application/json
    - application/xml
    - application/javascript
    - text/html
    - text/xml
    - text/plain
    - text/css
    - text/javascript
  # 默認只有響應體大于 2028kb 時才會進行壓縮
  min-response-size: 2048
  # 指定不壓縮的user-agent,默認為null
  # excluded-user-agents

對應的配置類:org.springframework.boot.context.embedded.Compression

最后

使用RestTemplate請求文本數(shù)據(jù)接口,發(fā)現(xiàn)解碼后的字符串是亂碼。此時除了編碼格式問題外就可以懷疑是不是服務器響應了壓縮后的數(shù)據(jù)。解決這個問題,先嘗試移除Accept-Encoding請求頭,告訴服務器,客戶端不需要壓縮響應體。如果服務器還是響應壓縮后的數(shù)據(jù),嘗試讀取服務器的Content-Encoding頭,根據(jù)服務器的壓縮編碼,自己再進行解壓縮。

到此這篇關于restemplate請求亂碼之content-encoding=“gzip“的文章就介紹到這了,更多相關restemplate請求亂碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • IDEA集成Sonar的完整流程

    IDEA集成Sonar的完整流程

    這篇文章主要介紹了IDEA集成Sonar的完整流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Eclipse中Properties和yml配置文件注釋亂碼的解決

    Eclipse中Properties和yml配置文件注釋亂碼的解決

    這篇文章主要介紹了Eclipse中Properties和yml配置文件注釋亂碼的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 通過Interface掃描獲取所有實現(xiàn)類方式

    通過Interface掃描獲取所有實現(xiàn)類方式

    文章介紹了如何使用ClassPathScanningCandidateComponentProvider從指定包中掃描接口實現(xiàn)類,并通過接口統(tǒng)一管理和獲取實現(xiàn)對象,這種方法避免了手動創(chuàng)建對象和修改代碼的問題,并且可以處理鏈路方式下的多處理器順序處理
    2025-11-11
  • SpringBoot整合RabbitMQ之路由模式的實現(xiàn)

    SpringBoot整合RabbitMQ之路由模式的實現(xiàn)

    本文主要介紹了SpringBoot整合RabbitMQ之路由模式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-06-06
  • Java中equals和hashcode用法

    Java中equals和hashcode用法

    `equals`和`hashCode`方法在Java中密切相關,必須保持一致性,如果兩個對象通過`equals`方法相等,它們的`hashCode`也必須相同,這對于基于哈希的數(shù)據(jù)結(jié)構(gòu)至關重要,因為這些結(jié)構(gòu)依賴哈希值進行快速查找和存儲,為了減少哈希沖突
    2025-01-01
  • Mybatis批量插入,返回主鍵ID不成功,巨坑記錄

    Mybatis批量插入,返回主鍵ID不成功,巨坑記錄

    這篇文章主要介紹了Mybatis批量插入,返回主鍵ID不成功,巨坑記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決

    springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決

    這篇文章主要介紹了springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決,文中有詳細的代碼示例供大家參考,對大家解決問題有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • SpringBoot定制化Starter實現(xiàn)方法

    SpringBoot定制化Starter實現(xiàn)方法

    小伙伴們曾經(jīng)可能都經(jīng)歷過整天寫著CURD的業(yè)務,都沒寫過一些組件相關的東西,這篇文章記錄一下SpringBoot如何自定義一個Starter。原理和理論就不用多說了,可以在網(wǎng)上找到很多關于該方面的資料,這里主要分享如何自定義
    2023-01-01
  • java?zxing合成復雜二維碼圖片示例詳解

    java?zxing合成復雜二維碼圖片示例詳解

    這篇文章主要為大家介紹了java?zxing合成復雜二維碼圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • JAVA位運算的知識點總結(jié)

    JAVA位運算的知識點總結(jié)

    在本篇文章里小編給大家整理的是關于JAVA有關位運算的全套梳理,需要的朋友們可以參考學習下。
    2020-03-03

最新評論

赣州市| 宜州市| 舒城县| 津南区| 枣庄市| 砀山县| 临汾市| 临汾市| 柘荣县| 杭州市| 枝江市| 望城县| 长宁县| 汨罗市| 贡山| 阳谷县| 尉犁县| 新郑市| 益阳市| 安庆市| 江阴市| 团风县| 建湖县| 临邑县| 雷山县| 莱阳市| 噶尔县| 得荣县| 抚远县| 普兰店市| 赤峰市| 凤冈县| 伊川县| 宁化县| 湛江市| 吉水县| 大竹县| 太康县| 东光县| 林州市| 常宁市|