最近项目上在迁移到k8s上部署,顺便也进行了一次spring版本升级,上线后就收到了ios端的反馈报障,ios端出现了乱码的情况。紧急回滚。
经过数据对比发现,http响应体分析,问题出在了返回的header里的Content-Type,升级后缺失了字符集,application/json;charset=UTF-8
spring-web 5.2+版本的 AbstractJackson2HttpMessageConverter类中默认字符集去掉了
/**
* The default charset used by the converter.
*/
@Nullable
@Deprecated
public static final Charset DEFAULT_CHARSET = null;
低版本的默认字符集是utf-8
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
当结果返回的时候AbstractHttpMessageConverter中方法addDefaultHeaders会构建header
if (contentTypeToUse != null) {
if (contentTypeToUse.getCharset() == null) {
Charset defaultCharset = getDefaultCharset();
if (defaultCharset != null) {
contentTypeToUse = new MediaType(contentTypeToUse, defaultCharset);
}
}
headers.setContentType(contentTypeToUse);
}
为什么要去掉呢?
看一下MediaType类中APPLICATION_JSON_UTF8_VALUE的解释
/**
* A String equivalent of {@link MediaType#APPLICATION_JSON_UTF8}.
* @deprecated as of 5.2 in favor of {@link #APPLICATION_JSON_VALUE}
* since major browsers like Chrome
*
* now comply with the specification and interpret correctly UTF-8 special
* characters without requiring a {@code charset=UTF-8} parameter.
*/
@Deprecated
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
意思是主流的浏览器已经默认都是支持utf-8的字符集了
怎么修复呢?
对返回内容进行类型转换的操作那必须是RequestMappingHandlerAdapter类
其中定义了messageConverters用于对结果数据进行转换
所以我们只需要遍历RequestMappingHandlerAdapter里的messageConverters,判断是MappingJackson2HttpMessageConverter 进行字符集修改就可以了
@Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@PostConstruct
public void init() {
requestMappingHandlerAdapter.getMessageConverters().forEach(c -> {
if (c instanceof MappingJackson2HttpMessageConverter) {
((MappingJackson2HttpMessageConverter) c).setDefaultCharset(Charset.forName("UTF-8"));
}
});
}