返回类型为ResponseEntity
代表我们返回的数据是一个对象,在springMVC中,请求数据到对象和对象到响应数据的转换是通过消息转换器来完成的。
HttpMessageConverter是消息转换器的顶层接口,所有的消息转换器都必须实现这个接口
package org.springframework.http.converter;
import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
public interface HttpMessageConverter {
boolean canRead(Class> clazz, MediaType mediaType);
boolean canWrite(Class> clazz, MediaType mediaType);
List getSupportedMediaTypes();
T read(Class extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
我们可以看到针对不同的类型,实现了具体消息转换器
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面先来说说 ,通过这个线索一直下去,找到问题的根源。
通常我们在springMVC配置文件中会配置
在 spring-webmvc.jar包下我们可以找到AnnotationDrivenBeanDefinitionParser类
分析getMessageConverters()方法后发现执行流程如下:
1.它首先会去配置中查找
2.然后判断message-converter是否为空。如果不为空,则把message-converter中封装的的所有自定义消息转换器添加到managedList集合中。
3.a)如果
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
…
private ManagedList> getMessageConverters(Element element, Object source, ParserContext parserContext) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
ManagedList super Object> messageConverters = new ManagedList
从其中我们可以找到添加StringHttpMessageConverter转换器的代码段
和之前输出JSON用到的MappingJackson2HttpMessageConverter转换器,这也可以看处springMVC对JSON的支持为什么要加入jackson的依赖。
我这里为什么要单独挑出这两个转换器,是为了说明他们的区别和调用时机的,和进一步引出问题。
a)之前如果我们要把对象以JSON格式输出,可以给controller的方法加@ResponseBody注解,到后来我们依照resultful的思想来做项目时,函数的返回值不会再是POJO,而是ResponseEntity
b)在SpringMVC中是怎么把我们的对象转换为JSON输出的呢,这里依旧要提到spring mvc的消息转换器,是它完成了这个转换过程。
c)但是函数值为ResponseEntity
接下来我们看StringHttpMessageConverter.class类 org.springframework.http.converter.StringHttpMessageConverter
public class StringHttpMessageConverter extends AbstractHttpMessageConverter {
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
private final Charset defaultCharset;
…
public StringHttpMessageConverter() {
this(DEFAULT_CHARSET);
}
public StringHttpMessageConverter(Charset defaultCharset) {
super(new MediaType("text", "plain", defaultCharset), MediaType.ALL);
this.defaultCharset = defaultCharset;
this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
}
…
}
发现它的默认转换编码是iso-8859-1,前台解码一般用utf-8,编解码不一致导致乱码,但我们发现这给类的构造方法预留了一个参数让我自己指定编码,这里我们看到了一丝希望哈哈。
解决办法:
我们只要在spring-mvc.xml配置文件中自己为这个消息转换器配置utf-8编码就ok了