Spring MVC 响应报文乱码

spring 4.2.2 responsebody 乱码 utf-8

乱码问题一直是个比较头疼的话题,因为造成乱码的罪魁祸首千奇百怪,乱七八糟。。。
本文就作为收集各种与Spring MVC相关的案例的合集,持续更新吧。

前提

  • 应答报文都是JSON格式,即通过@RequestMapping中的produces={application/json}属性实现

线索梳理

1. 确认Controller中返回对象类型
Spring MVC返回Json字符串基本使用两种方式,第一,controller的方法直接返回Json格式的字符串, 第二, 返回Form,List, Map之类的可序列化对象,配置Spring集成Jackson进行json转换。

2. 确认StringHttpMessageConverter的配置编码(方式一)
因为controller返回的已经是字符串, Spring只需将其刷入response的outputStream中即可。但是刷入的时候用的具体编码是什么呢?
查看StringHttpMessageConverter的源码可以看到 DEFAULT_CHARSET = Charset.forName("ISO-8859-1"), 只需要在dispatcher-servlet.xml中将其修改为UTF-8即可。

 
    
        
            
                
                
                
            
        
    
 

3. 确认MappingJackson2HttpMessageConverter的配置编码(方式二)
该转换类的默认编码是UTF-8, 所以这里应该不会出现编码问题。如果手动配置是这样的。

 
    
        
            text/html;charset=UTF-8
            application/json;charset=UTF-8
        
    
 

4. Spring API 过时
当dispatcher-servlet.xml中使用时,如果是3.1之前已经默认注入AnnotationMethodHandlerAdapter,3.1之后默认注入RequestMappingHandlerAdapter。所以如果没有使用,需要手动添加声明,示例如下

 
    
        
            
                
                    
                        text/html;charset=UTF-8
                        application/json;charset=UTF-8
                    
                
            
        
    
 

 
    
        
            
                
                    text/plain; charset=UTF-8
                    text/html; charset=UTF-8
                    application/json; charset=UTF-8
                
            
        
        
            
                
                    application/json; charset=UTF-8
                    application/x-www-form-urlencoded; charset=UTF-8
                
            
        
    

乱码场景1

controller中的方法定义如下,所以满足方式一,使用了,最终应答报文乱码。
解决方案有两种:
A. produces的值修改为 {"application/json; charset=utf-8"}, 最简单直观,但是所有的方法上面都要修改;
B. dispatcher-servlet.xml 中添加StringHttpMessageConverter的配置是没用的,因为你会发现怎么都不能生效!这是因为produces里面的只设定了 application/json, 在 StringHttpMessageConverter.getContentTypeCharset(MediaType contentType)的入参中, MediaType永远只有application/json, 获取不到charset!
可采用上方 中添加 converter的方式,并确保删除 produces。

这个场景最终只说明一个问题,produces中的MediaType要完整,包括type(application) subtype(json)和charset(utf-8)

@RequestMapping(value = "queryIdCard", method = RequestMethod.POST, produces = {"application/json"})
@ResponseBody
public String queryIdCard(@RequestBody String idCardNo) {
    MeResponse response = idCardBusiness.queryPersonInfo(idCardNo);
    return JsonUtil.toJsonString(response);
}

你可能感兴趣的:(Spring MVC 响应报文乱码)