前言
- 在
SpringMVC
中,可以使用@RequestBody
和@ResponseBody
两个注解,分别完成请求报文到对象和对象到响应报文的转换,底层这种灵活的消息转换机制,就是Spring3.x
中新引入的HttpMessageConverter
即消息转换器机制。而这种消转换机制的原理是什么,大家可以去具体的分析一下SpringMvc
的源码。
HttpMessageConverter机制大致原理
- 当我们在
Handler
的某个方法上加上注解@ResponseBody
后,服务器可以给客户端返回json
格式的数据,当然,其本质就是字符串。因为Http
请求和响应报文本质上都是一串字符串,当请求报文来到java世界,它会被封装成为一个ServletInputStream
的输入流,供我们读取报文。响应报文则是通过一个ServletOutputStream
的输出流,来输出响应报文。 - 我们从输入流中,只能读取到原始的字符串报文,同样,我们在输出流中,也只能写原始的字符。而在java世界中,处理业务逻辑,都是以一个个有业务意义的对象为处理维度的,那么在报文到达
SpringMVC
和从SpringMVC
出去,都存在一个字符串到java对象的阻抗问题。这一过程,不可能由开发者手工转换。 -
下面是原理的大致流程图
遇到的问题
@ResponseBody加到某个返回String的方法上时,当方法返回字符串中有汉字时,客户端接收到就会产生乱码问题,具体Demo如下所示。
@ResponseBody
@RequestMapping(value="/queryJson")
public String queryJson(HttpServletRequest request,HttpServletResponse response,Model model) throws Exception {
//将学生信息列表在页面上展示
List<Student> list = new ArrayList<Student>();
Student student = new Student();
student.setId("id1");
student.setName("小学生");
student.setAge(8);
student.setAddress("北京市海淀区");
list.add(student);
return list.toString();
}
返回效果图
- 本来name应该显示为“小学生”,address显示成”北京市海淀区”,但是现在全部变成了? 这是怎么一回事那?
问题的原因
- 这个问题的原因是
HttpMessageConverte
机制在处理请求和响应的时候出现的问题,Springmvc
有一系列HttpMessageConverter
去处理用@ResponseBody
注解的返回值,如返回list或其它则使用MappingJacksonHttpMessageConverter
,若返回String,则使用StringHttpMessageConverter
,而返回String这个convert使用的是字符集是iso-8859-1
,而且是final的。所以在当返回String中有中文时会出现乱码。下面是源码。
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
解决方法
在@RequestMapping中设置一下MediaType
@RequestMapping(value="/queryJson", produces =MediaType.APPLICATION_JSON_VALUE)
或者这样
@RequestMapping(value="/queryJson", produces ="application/json" + ";charset=utf-8")
这两个效果是一样的
在springmvc配置文件设置
<mvc:annotation-driven>
<mvc:message-converters>
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=utf-8</value>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
小结
- 解决方式不止一种,个人推荐第二种方式,这种方式一劳永逸,方便程序员开发。