背景故事是某些SpringBoot服务,在某次部署至某环境后,前端展示异常。服务请求响应如下:
由上图可推测该服务所在环境系统编码为ISO-8899-1,忘记设置为UTF-8;又已知JVM中在IO时字符串的默认字符集取自系统属性file.encoding,则解决办法如下:
-
JVM启动时传入参数[ -Dfile.encoding=UTF-8 ]: .
-
设置操作系统编码:
查看当前编码=> locale 或者 echo $LANG
查看系统支持编码=> locale -a
然后调整=> 例如centos7,修改 /etc/locale.conf 文件中的键值对LANG=zh_CN.UTF-8 -
若是docker集群,dockerfile增加命令:
或者
ENV LC_ALL=zh_CN.utf8 ENV LANG=zh_CN.utf8 ENV LANGUAGE=zh_CN.utf8 RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
-
maven在编译过程中,设定编码
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <java.version>1.8</java.version> </properties>
PS :JVM内部字符编码以及编译后的字节码都是unicode / UTF-16 。
以上操作后,问题仍未解决,但发现日志已经能正常展示中文。
-
调整SpringBoot编码,此方法是不懂机制直接走捷径,应该直接自己手写编码过滤器。
# application.properties spring.http.encoding.force=true spring.http.encoding.enabled=true spring.http.encoding.charset=UTF-8
到此问题仍未解决,但考虑到问题出在环境,没有尝试没有真的手动编写过滤器。
- 更换基础镜像。
Dockerfile是多阶段构建的,第一阶段maven编译程序,第二阶段使用jre运行程序。我更换了jre基础镜像,果然ISO-8899-1变为UTF-8。但乱码依旧存在,所以怀疑maven编译环节的基础镜像也有编码问题,导致程序在这个环境下编译不符预期。但最终证明本质因素不在这。
最终确定还是SpringBoot应用本身的问题,当初因为种种误会原因没有认为这是首要方向。