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

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

 更新時(shí)間: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 并且實(shí)現(xiàn)了 RestOperations 接口,其中 RestOptions 接口定義了基本的 RESTful 操作,這些操作在 RestTemplate 中都得到了實(shí)現(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設(shè)置的也是UTF-8。在翻看其他博客,發(fā)現(xiàn)問題原因是http存在一個壓縮格式:Gzip。

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

響應(yīng)頭中的gzip

Content-Encoding

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

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

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

Accept-Encoding

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

注:一般是客戶端使用,表示給服務(wù)器說明,客戶端支持的壓縮算法列表。服務(wù)從中選擇一個對響應(yīng)體進(jìn)行壓縮。

/**
     * @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 表示客戶端支持什么格式的響應(yīng)體
                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){
                    // 獲取服務(wù)器響應(yīng)體編碼
                    String contentEncoding = forEntity.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
                    if ("gzip".equals(contentEncoding)) { // 是gzip編碼
                        // gzip解壓服務(wù)器的Body響應(yīng)體
                        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("和風(fēng)API響應(yīng)值編碼不是Gzip,請聯(lián)系我,謝謝");
                    }
                }else{
                    result.setErrored("和風(fēng)API響應(yīng)出錯了");
                }
            }
        }
    }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的響應(yīng)體壓縮配置

實(shí)際上,并不需要自己手動去寫這種響應(yīng)體的壓縮代碼。springboot提供了相關(guān)的配置。只針對響應(yīng)壓縮

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

對應(yīng)的配置類:org.springframework.boot.context.embedded.Compression

最后

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

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

相關(guān)文章

  • IDEA集成Sonar的完整流程

    IDEA集成Sonar的完整流程

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

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

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

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

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

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

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

    Java中equals和hashcode用法

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

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

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

    springcloud連接遠(yuǎn)程nacos失敗顯示localhost服務(wù)連接失敗的問題解決

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

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

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

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

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

    JAVA位運(yùn)算的知識點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于JAVA有關(guān)位運(yùn)算的全套梳理,需要的朋友們可以參考學(xué)習(xí)下。
    2020-03-03

最新評論

彭阳县| 广宗县| 双桥区| 都昌县| 乌拉特前旗| 勐海县| 张家界市| 鄂伦春自治旗| 惠东县| 穆棱市| 香河县| 醴陵市| 汽车| 大城县| 鄂州市| 铜梁县| 西贡区| 周口市| 泾川县| 通城县| 鲜城| 嘉善县| 肥城市| 仁怀市| 梅河口市| 北安市| 宁强县| 新源县| 平昌县| 丹棱县| 松阳县| 隆回县| 本溪市| 宜春市| 雷波县| 东乡| 金乡县| 霸州市| 建阳市| 合肥市| 瓦房店市|