Spring boot 字符集编码
Posted 417xiaoliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring boot 字符集编码相关的知识,希望对你有一定的参考价值。
来源
近一段在开发接口平台,使用spring boot 开发,总体来说还是蛮顺利;
接口平台不可避免的让别人调用服务,也会去调用其它的外部接口;
突然有一天,某个服务商回调信息中出现了乱码,形如:??????
,打破了宁静
分析过程
向服务商确认,该接口传递的参数使用GBK编码,WHT??现在还有用GBK的,不是用UTF8编码么?
马上确认我的程序编码:
server.tomcat.uri-encoding 未设置
http.encoding.charset: UTF-8
http.encoding.force-request: true
可以看到uri的配置未定义,搜索文档说明spring boot默认使用UTF8编码
下面两个是定义HTTP的字符集,用来设置request与response的字符集;
跟踪源码,发现这个字符参数会在CharacterEncodingFilter中用到,核心的方法是使用:request.setCharacterEncoding("UTF-8")
,并且是一个全局的内容
解决过程
将得到的乱码用UTF-8编码再用GBK解码,如下代码,得到结果为:
锟斤拷值失锟斤拷
new String(source.getBytes("UTF-8"),"GBK")
, 通过查资料得知,以GBK编码->UTF-8解码(出现乱码)->UTF-8编码(这步由于UTF8编码的特殊性,会增加部分头信息)->GBK解码(由于加了特殊部分,所以造成不可逆的结果)在方法中调用
request.getCharacterEncoding("UTF-8")
无效,查询rquest的这个方法说明,只有在获取参数之前调用这个方法才有效,但在此之前spring 已帮我们做了很多事情,所以在这里无效;自已写Filte来实现设置,但不知什么原因,还是无效
继承
CharacterEncodingFilter
,对特定url做特殊处理,结果是自定义的encoding生效了,原先的UTF8的 encodingFilter失效了,就算修改自己的Bean名字还不行修改自定义EncodingFilter,实现多字符集的处理:
定义encodingFilter:
public class MutiCharacterEncodingFilter extends CharacterEncodingFilter implements Ordered{
//最高优先级
private int order = Integer.MIN_VALUE;
private List<String> mutiUrls = new ArrayList();
private String mutiCharset = "GBK";
public List<String> getMutiUrls() {
return mutiUrls;
}
public void setMutiUrls(List<String> mutiUrls) {
this.mutiUrls = mutiUrls;
}
public String getMutiCharset() {
return mutiCharset;
}
public void setMutiCharset(String mutiCharset) {
this.mutiCharset = mutiCharset;
}
/**
* @param charset
* @param mutiCharset
* @param mutiUrls
* @param forceRequest
* @param forceResponse
*/
public MutiCharacterEncodingFilter(String charset, String mutiCharset , List<String> mutiUrls, boolean forceRequest, boolean forceResponse) {
super(charset,forceRequest,forceResponse);
this.mutiUrls = mutiUrls;
this.mutiCharset = mutiCharset;
}
public MutiCharacterEncodingFilter() {
super();
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String path = request.getRequestURI();
//如果是这个链接 执行mutyEncoding方法
if(PathMatcherUtil.matchAny(mutiUrls,path)){
if (mutiCharset != null) {
if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(mutiCharset);
}
if (isForceResponseEncoding()) {
response.setCharacterEncoding(mutiCharset);
}
}
filterChain.doFilter(request,response);
return ;
}
//否则 使用默认方法
super.doFilterInternal(request,response,filterChain);
}
@Override
public int getOrder() {
return order;
}
在配置中设置相应内容:
http:
encoding:
charset: UTF-8
force-request: true
force-response: false
mutiCharset: GBK
mutiUrls:
- /notify/test
在config中生成实例
//第一种字符集
@Value(value = "${spring.http.encoding.charset}")
private String charset;
//是否强制应用到request
@Value(value = "${spring.http.encoding.force-request}")
private boolean forceRequest;
//是否强制设置到response
@Value(value = "${spring.http.encoding.force-response}")
private boolean forceResponse;
/**
* 自定义HTTP字符集 默认使用charset字符集 在特定情况下使用第二字符集 用于欧飞回调GBK编码
* 仅对POST中的表单参数有效 对于URI中的参数无效 只能去修改tomcat的字符集编码 应该不致于做的这么绝吧
* @return
*/
@Bean()
@ConfigurationProperties(prefix = "spring.http.encoding")
@ConfigurationPropertiesBinding
public MutiCharacterEncodingFilter mutiCharacterEncodingFilter(){
MutiCharacterEncodingFilter encodingFilter = new MutiCharacterEncodingFilter();
encodingFilter.setEncoding(charset);
encodingFilter.setForceRequestEncoding(forceRequest);
encodingFilter.setForceResponseEncoding(forceResponse);
return encodingFilter;
}
到此问题解决,可以接收GKB编码的内容;
但同时也有缺陷,只适用于body的内容,不适用于链接到URL后面的请求参数,如果要支持,只能修改tomcat-uri-encoding为UTF-8,希望对大家有帮助.
以上是关于Spring boot 字符集编码的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot:thymeleaf 没有正确渲染片段
spring boot + thymeleaf 无法正确编码 POST 中的 UTF-8 字符
解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式