restemplate请求乱码之content-encoding=“gzip“

2024-03-28 13:04

本文主要是介绍restemplate请求乱码之content-encoding=“gzip“,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

restemplate请求乱码之content-encoding="gzip"

  • 响应头中的gzip
    • Content-Encoding
    • Accept-Encoding
  • SpringBoot的响应体压缩配置
  • 最后

今天有一个通过Restemplate请求一个天气API,发现其Body数据是乱码,同事处理了好久,然并卵,经检查后,发现头部信息出了问题。

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

返回值是UTF-8,Restemplate设置的也是UTF-8。在翻看其他博客,发现问题原因是http存在一个压缩格式:Gzip。

Gzip是一个压缩算法,当请求数据或返回数据体积过大,为减少网络负载压力而使用的压缩算法。通常在服务器端使用,客户端为获得原始数据需通过Gzip解压。

响应头中的gzip

Content-Encoding

是一个实体消息首部,用于对特定媒体类型的数据进行压缩。当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。

一般建议对数据尽可能地进行压缩,因此才有了这个消息首部的出现。

注:客户端和服务器都可以使用,表示body中的数据采用了什么编码(压缩算法)

Accept-Encoding

HTTP 请求头 Accept-Encoding 会将客户端能够理解的内容编码方式——通常是某种压缩算法——进行通知(给服务端)。通过内容协商的方式,服务端会选择一个客户端提议的方式,使用并在响应头 Content-Encoding 中通知客户端该选择。

注:一般是客户端使用,表示给服务器说明,客户端支持的压缩算法列表。服务从中选择一个对响应体进行压缩。

在这里插入图片描述

/*** @Title: getClimateByRequst* @Description: ( 通过request 获取天气信息)* @Author:lijie* @since 2021/11/9 14:05* @Version:1.1.0* @return:   climate:封装的天气结果类*/
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=""//请求的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");//发送请求 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,请联系我,谢谢");}}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压缩数据* @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请求文本数据接口,发现解码后的字符串是乱码。此时除了编码格式问题外就可以怀疑是不是服务器响应了压缩后的数据。解决这个问题,先尝试移除Accept-Encoding请求头,告诉服务器,客户端不需要压缩响应体。如果服务器还是响应压缩后的数据,尝试读取服务器的Content-Encoding头,根据服务器的压缩编码,自己再进行解压缩。

这篇关于restemplate请求乱码之content-encoding=“gzip“的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855694

相关文章

Spring Boot Controller处理HTTP请求体的方法

《SpringBootController处理HTTP请求体的方法》SpringBoot提供了强大的机制来处理不同Content-Type​的HTTP请求体,这主要依赖于HttpMessageCo... 目录一、核心机制:HttpMessageConverter​二、按Content-Type​处理详解1.

一文详解如何在Vue3中封装API请求

《一文详解如何在Vue3中封装API请求》在现代前端开发中,API请求是不可避免的一部分,尤其是与后端交互时,下面我们来看看如何在Vue3项目中封装API请求,让你在实现功能时更加高效吧... 目录为什么要封装API请求1. vue 3项目结构2. 安装axIOS3. 创建API封装模块4. 封装API请求

Python与Java交互出现乱码的问题解决

《Python与Java交互出现乱码的问题解决》在现代软件开发中,跨语言系统的集成已经成为日常工作的一部分,特别是当Python和Java之间进行交互时,编码问题往往会成为导致数据传输错误、乱码以及难... 目录背景:为什么会出现乱码问题产生的场景解决方案:确保统一的UTF-8编码完整代码示例总结在现代软件

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Spring 请求之传递 JSON 数据的操作方法

《Spring请求之传递JSON数据的操作方法》JSON就是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,因此JSON本质是字符串,主要负责在不同的语言中数据传递和交换,这... 目录jsON 概念JSON 语法JSON 的语法JSON 的两种结构JSON 字符串和 Java 对象互转

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多