springboot项目,版本2.3.5,系统编码是utf-8。但是合作方请求的时候Content-Type是application/x-www-form-urlencoded;charset=GBK,用@RequestParam 接受参数map的时候乱码了。但是HttpServletRequest.getInputStream()中获取的是正常的。
正常HttpServletRequest.getInputStream()获取的结果是:%5B%BA%EC%C9%BD%C9%AD%C1%D6%B6%AF%CE%EF%D4%B0-%B4%F3%C3%C5%C6%B1%5D%C4%CF%BE%A9%BA%EC%C9%BD%C9%AD%C1%D6%B6%AF%CE%EF%D4%B0%B3%C9%C8%CB%C6%B1%B4%F3%C3%C5%C6%B1 ,这样直接urldecode(var,"GBK")就可以了。
但是不管是通过@RequestParam获取map还是通过@RequestBody获取字符串,字符串都变成了:%5B%EF%BF%BD%EF%BF%BD%C9%BD%C9%AD%EF%BF%BD%D6%B6%EF%BF%BD%EF%BF%BD%EF%BF%BD%D4%B0-%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%C6%B1%5D%EF%BF%BD%CF%BE%EF%BF%BD%EF%BF%BD%EF%BF%BD%C9%BD%C9%AD%EF%BF%BD%D6%B6%EF%BF%BD%EF%BF%BD%EF%BF%BD%D4%B0%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%C6%B1%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%C6%B1
这感觉像是又被编码了一次。然后就怎么都解不开了。
有人遇到过这个问题吗?@RequestBody和@RequestParam 是怎么把数据封装到参数里的啊?感觉就是这里面出了问题。
还有个现象:在springboot2.1.4版本的时候,只要设置CharacterEncodingFilter就可以了。
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
return filter;
}
这是强制转utf8,但是因为版本升级了,这个配置没有效果。
server:
servlet:
encoding:
charset: UTF-8
force: true
然后2.3.5版本版本添加上面的配置也没有效果。
搞了一天,终于弄明白了。
springboot 2.3.5中默认的编码是UTF-8,查看Encoding类中方法shouldForce
public boolean shouldForce(Type type) {
Boolean force = (type != Type.REQUEST) ? this.forceResponse : this.forceRequest;
if (force == null) {
force = this.force;
}
if (force == null) {
force = (type == Type.REQUEST);
}
return force;
}
可以看出默认request是强制转成UTF-8的。也就是request.getCharacterEncoding获取的是UTF-8。那么在获取参数的时候就会用UTF-8来解码。
但是如果配置不强制转换的话,则从请求头信息ContentType中的编码格式来转换,比如设置ContentType是application/x-www-form-urlencoded;charset=GBK,则用GBK来转换。
private static String getCharsetFromContentType(String contentType) {
if (contentType == null) {
return null;
}
int start = contentType.indexOf("charset=");
if (start < 0) {
return null;
}
String encoding = contentType.substring(start + 8);
int end = encoding.indexOf(';');
if (end >= 0) {
encoding = encoding.substring(0, end);
}
encoding = encoding.trim();
if ((encoding.length() > 2) && (encoding.startsWith("\""))
&& (encoding.endsWith("\""))) {
encoding = encoding.substring(1, encoding.length() - 1);
}
return encoding.trim();
}
所以这种情况只要修改配置文件就行了,也就是force-request=false
server:
servlet:
encoding:
charset: UTF-8
force-request: false
如果请求头信息ContentType里没有charset,那么默认还是UTF-8
@RequestMapping(produces = “application/x-www-form-urlencoded;charset=GBK”, method = RequestMethod.POST),这样设置一下?
apringmvc提供了参数解析器来实现参数绑定,对于不同的注解以及contentType,调用不同的实现类!你这种的话,和别人约定好,到底是走json还是不走json,走json的话,可以实现requestBobyAdvise,不走json,可以用自己去实现filter