后端常用技能:解决java项目前后端传输数据中文出现乱码、问号问题
0. 问题背景
最近做一个解析数据的小工具,本地运行时都正常,发布到服务器上后在导出文件数据时发现中文全部变成了问号,特此记录下问题解决的思路和过程
1. 环境
java 1.8
springboot 2.6.13
额外引入了fastjson
,commons-csv
等依赖
2. 解决过程
思路1:后端响应体及前端blob对象声明编码格式为utf8
1、首先该问题在本地未发现,服务器上出现了,因此可以明确的是环境编码方式不一致导致的
2、一开始我以为在生成导出数据时出现的问题,项目涉及将导入的文本文件数据解析后导出为csv格式的excel数据
于是首先在导出时,在响应体中声明编码格式为utf8
response.setContentType("application/octet-stream;charset=utf-8");
同时我前端的处理,是将文件流数据转换为blob对象,然后进行文件下载,于是将生成blob对象的地方也声明编码格式
/*** 文件流转换为blob对象进行下载* @param data 后端返回的文件流数据* @param filename 文件名*/
function exportBlob(data, filename) {let blob = new Blob([data], {type: "application/octet-stream,charset=UTF-8"});// 创建一个下载链接const url = window.URL.createObjectURL(blob);// 创建一个隐藏的<a>元素,并设置其href属性为下载链接const a = document.createElement('a');a.href = url;a.download = filename;// 将<a>元素添加到页面中,并模拟点击document.body.appendChild(a);a.click();// 完成下载后,移除<a>元素和下载链接document.body.removeChild(a);window.URL.revokeObjectURL(url);
}
3、该方式本地运行正常,发布服务器后仍然有中文为问号的问题。于是继续分析
思路2:application.properties中设置全局编码格式
1、前面已经明确的是:服务器编码格式不一致导致的,于是通过locale
指令查询服务器编码格式
如上图,发现服务器默认配置的编码格式是utf8
2、但结合实际情况,说明服务器编码格式肯定不是utf8,有时因为安装了一些额外的插件会导致服务器的编码格式被更改
同时怀疑数据在输入时就已经乱码了,于是在后端接口,接收输入参数时打印了数据,发现果然解析的中文就是问号,这就说明问题是出在前端传输给后端的数据中文乱码了,而不是后端返回给前端的数据乱码了。
3、怀疑是前后端的传输编码格式不统一导致的,于是在前端ajax请求中声明数据编码格式UTF-8
$.ajax({url: 'json/export',type: 'POST',contentType: "application/x-www-form-urlencoded;charset=UTF-8",data: {json: json},success: function (data, textStatus, xhr) {layer.close(load);if(data.msg != null){layer.msg(data.msg, {icon: 5});}else{exportBlob(data, "json转换输出数据.csv");layer.msg("导出成功");}},error: function (xhr, status, error) {layer.msg("导出失败");layer.close(load);console.log(xhr);}});
4、同时在后端声明编码格式,因为是springboot项目,所以直接在application.properties
中配置:
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
因为我这里springboot版本是2.3+,低版本中应该是
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
该配置可以让服务端在接收和发送数据时使用UTF-8编码
5、再次在服务器上运行,发现还是有中文乱码问题
6、怀疑该配置没生效,于是手写了一个配置类,用于声明编码格式
@Configuration
public class WebConfig implements WebMvcConfigurer
{@Beanpublic FilterRegistrationBean characterEncodingFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean(new CharacterEncodingFilter());registration.addInitParameter("encoding", "UTF-8");registration.addInitParameter("forceEncoding", "true");registration.addUrlPatterns("/*");return registration;}private static class CharacterEncodingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html; charset=UTF-8");chain.doFilter(request, response);}}
}
7、服务器上运行,问题还是没解决,说明不是该问题导致
思路3:重新编码传输数据
1、如上我们已经将服务端编码格式设置为utf8了,解析仍然有问题,于是尝试将传入数据二次编码
导入文件解析:
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.ISO_8859_1);
字符串参数解析:
json = new String(json.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
2、然后本地运行,发现就出现问题了,本地运行也出现中文乱码了,那么说明编码格式ISO_8859_1肯定不行
3、于是尝试根据环境本身的编码格式去设置
打印了下服务器上的编码格式
log.error("编码:"+ Charset.defaultCharset().name());
服务器打印结果
这里就可以看到服务器上编码果然不是utf8,于是重新设置编码:
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.defaultCharset());
json = new String(json.getBytes(Charset.defaultCharset()), StandardCharsets.UTF_8);
4、服务器上运行,依然出现中文乱码
思路4:jvm启动脚本中添加-Dfile.encoding=utf-8
1、目前我们能确定的是服务器的编码格式不是utf8,而是US-ASCII。但在代码中二次编码的形式行不通,这里思路有些阻塞了。可以明确的就是环境编码格式导致的,但是怎么定义环境的编码格式呢? 从项目内部定义的形式似乎都行不通
2、自己思路阻塞的时候一般有两种解决办法:
(1)放一放,过几个小时或者第二天再来看,这是思路清空,相对受之前惯性思维的影响较小,一般这时再来看有奇效
(2)与其他人讨论,融合新的思路
3、这里因为想当天把这个问题解决了,于是采取了第二种与同事进行了交流,刚好同事给我说他之前遇到过一种中文乱码的情况,通过在启动脚本里设置-Dfile.encoding=utf-8
解决的
于是进行了尝试,在java项目的启动脚本的添加了该配置
JAVA_OPTS="-server -Xms1G -Xmx2G -Xmn256m -Xss1m \
-Dfile.encoding=utf-8 \
-XX:SurvivorRatio=4 -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection \
-XX:CMSInitiatingOccupancyFraction=60 -XX:+PrintGCDateStamps \
-XX:+PrintGCDetails -Xloggc:$LOGS_DIR/gc.log"
4、重启项目,发现中文显示正常了,同时打印的编码格式也变成utf8了。问题解决
5、这里再回过头来看时,发现确实是自己思路陷入局限了,明明知道是环境的问题,却一直期望通过项目内配置解决。
实际上java通过jvm运行,其环境编码问题,自然应该从jvm配置着手。
-Dfile.encoding=utf-8
的作用就是设置jvm虚拟机的编码格式,java项目默认字符集是在java虚拟机启动时决定的,依赖于java虚拟机所在的操作系统的区域以及字符集
实际上该配置应该作为我们项目的常用配置,此次也是因为临时做个新工具,忽略了该配置的书写
总结
如上,就是我针对java项目出现中文乱码的问题的解决思路及过程,对比了网上说明的解决方法,发现也基本上涵盖了大多数情况,大家可以参考
相关文章:

后端常用技能:解决java项目前后端传输数据中文出现乱码、问号问题
0. 问题背景 最近做一个解析数据的小工具,本地运行时都正常,发布到服务器上后在导出文件数据时发现中文全部变成了问号,特此记录下问题解决的思路和过程 1. 环境 java 1.8 springboot 2.6.13 额外引入了fastjson,commons-csv等…...

SpringBoot中使用MongoDB
目录 搭建实体类 基本的增删改查操作 分页查询 使用MongoTemplate实现复杂的功能 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> 在ap…...

【TS】入门
创建项目 vscode自动编译ts 生成配置文件 tsc --init 然后发现终端也改变了:...

Apache ECharts
Apache ECharts介绍: Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。 官网地址:https://echarts.apache.org/zh/index.html Apache ECh…...

超详细的胎教级Stable Diffusion使用教程(四)
这套课程分为五节课,会系统性的介绍sd的全部功能和实操案例,让你打下坚实牢靠的基础 一、为什么要学Stable Diffusion,它究竟有多强大? 二、三分钟教你装好Stable Diffusion 三、小白快速上手Stable Diffusion 四、Stable dif…...

串口属性中的BM延时计时器问题
如果使用程序修改则需要修改注册表对应位置如下 第一个示例(217) 第二个示例(219) 需要注意的事情是修改前必须点查看串口名称(例如上图是com5) 程序修改: 有没有办法以编程方式更改USB <…...

PyQt6--Python桌面开发(8.QPlainTextEdit纯文本控件)
QPlainTextEdit纯文本控件...

Java | Leetcode Java题解之第83题删除排序链表中的重复元素
题目: 题解: class Solution {public ListNode deleteDuplicates(ListNode head) {if (head null) {return head;}ListNode cur head;while (cur.next ! null) {if (cur.val cur.next.val) {cur.next cur.next.next;} else {cur cur.next;}}return…...

重生奇迹mu再生宝石怎么用有什么用
重生奇迹mu再生宝石有2个用处: 1、在玛雅哥布林处给380装备加PVP属性4追4以上的380级装备,守护宝石一颗,再生宝石一颗,成功得到PVP装备,失败宝石消失,装备无变化; 2、给非套装点强化属性用法跟祝福,灵魂,生命一样直接往装备上敲,成功得到随机强化属性一…...
pdf 文件版面分析--pdfplumber (python 文档解析提取)
pdfplumber 的特点 1、它是一个纯 python 第三方库,适合 python 3.x 版本 2、它用来查看pdf各类信息,能有效提取文本、表格 3、它不支持修改或生成pdf,也不支持对pdf扫描件的处理 import glob import pdfplumber import re from collection…...

PostgreSQL的学习心得和知识总结(一百四十三)|深入理解PostgreSQL数据库之Support event trigger for logoff
目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…...

https免费证书获取
获取免费证书的网址: Certbot 1. 进入你的linux系统,先安装snapd, yum install snapd 2. 启动snapd service snapd start 3.安装 Certbot snap install --classic certbot 注意如下出现此错误时,需要先建立snap 软连接后&am…...

C语言 | Leetcode C语言题解之第74题搜索二维矩阵
题目: 题解: bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {int m matrixSize, n matrixColSize[0];int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 low;int x matrix[mid /…...

杰发科技AC7840——软件Sent_HAL39X
0. 序 使用PWM模拟Sent测试下7840的软件sent功能。 参考链接:SENT协议应用笔记 - TechPlus汽车工坊的文章 - 知乎 SENT协议 1. Sent功能测试 使用提供的软件Sent代码在7840上测试,接收数据OK 2. 参考资料 3. 数据解析 我们个根据上述参考资料尝试解析…...

IOS 开发 - block 使用详解
1.Blobk的定义 block的写法相对难记,不必司机应被,只需要在xcode里打出"inlineBlock"--回车, 系统会自动帮你把基础版写法给你匹配出来 //Block的基础声明//等号""之前是blobk的声明,等号“”后面是block的实现/*returnType:返回类型(void、int、String *…...

BUU-[极客大挑战 2019]Http
考察点 信息收集 http构造请求数据包 题目 解题步骤 参考文章:https://zhuanlan.zhihu.com/p/367051798 查看源代码 发现有一个a标签,但是οnclick"return false"就是点击后不会去跳转到Secret.php的页面 所以我就自己拼接url http://no…...

开发Web3 ETF的技术难点
开发Web3 ETF(Exchange-Traded Fund,交易所交易基金)软件时,需要注意以下几个关键问题。开发Web3 ETF软件是一个复杂的过程,涉及到金融、法律和技术多个领域的专业知识。开发团队需要综合考虑上述问题,以确…...
【K8s】Kubectl 常用命令梳理
Kubectl常用命令梳理 下面包含大致涵盖命令只需要替换对应的Pod \ NameSpace 查看 命名空间 是 ’worktest2‘ 下 名字包括 ’todo‘的所有 Pod kubectl -n worktest2 get pod|grep todo查看 所有命名空间下 名字包括 ’todo‘的所有 Pod kubectl get pods --all-namespace…...
机器学习-监督学习
监督学习是机器学习和人工智能中的一个重要分支,它涉及使用已标记的数据集来训练算法,以便对数据进行分类或准确预测结果。监督学习的核心在于通过输入数据(特征)和输出数据(标签或类别)之间的关系…...

搭建Docker私服镜像仓库Harbor
1、概述 Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。 Harbor 的所有组件都在 Dcoker 中部署,所以 Harbor 可使用 Docker Compose 快速部署。 …...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...