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

相关文章

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

SpringBoot请求参数传递与接收示例详解

《SpringBoot请求参数传递与接收示例详解》本文给大家介绍SpringBoot请求参数传递与接收示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录I. 基础参数传递i.查询参数(Query Parameters)ii.路径参数(Path Va

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

RedisTemplate默认序列化方式显示中文乱码的解决

《RedisTemplate默认序列化方式显示中文乱码的解决》本文主要介绍了SpringDataRedis默认使用JdkSerializationRedisSerializer导致数据乱码,文中通过示... 目录1. 问题原因2. 解决方案3. 配置类示例4. 配置说明5. 使用示例6. 验证存储结果7.

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1