开始接触使用springmvc的时候, 返回controller 内容中文乱码。
百度一下,然后配置 messageConverters 加上
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/plain; charset=UTF-8</value>
</list>
</property>
</bean>
即解决了中文乱码。
假设我们不加上 json 数据的消息处理
比如
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
那么 如果 controller 返回 对象或者json 对象肯定会报错:HttpMediaTypeNotAcceptableException: Could not find acceptable representation
因为 没有 对应消息处理器 处理该返回值,MediaType 类型返回的 contenType 类型肯定是 application/json
StringHttpMessageConverter 处理返回的 contenType 是 text 或者 plain
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:126)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:189)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:69)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
在 messageConverters 加上 <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
即可解决了,也就是 controller 可以直接 返回对象 了。
就是这样解决了问题。其实不太明白这样配置的意思。
解惑
StringHttpMessageConverter
StringHttpMessageConverter 只能对 controller 的 返回 string 类型的内容进行 处理,
如果是其他的对象, 甚至是 controller 返回的 int 类型, spirngmvc 也不会使用 StringHttpMessageConverter 对返回的内容进行处理的。
会将 StringHttpMessageConverter 忽略掉,如果没有 消息处理器对这个返回结果进行处理,那么就会 抛出 :
HttpMediaTypeNotAcceptableException: Could not find acceptable representation 异常
那么为什么 不配置 StringHttpMessageConverter 会导致中文乱码?
因为 查看一下 StringHttpMessageConverter 源码可以知道, StringHttpMessageConverter 默认的编码
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
使用了这个,如果不配置指定 ISO-8859-1 肯定中文乱码了。
而 StringHttpMessageConverter 有一个 构造方法,允许指定 编码
因此
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
即可 解决中文乱码。
即supportedMediaTypes 配置不指定 编码也是不会中文乱码的
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain</value>
<value>text/html</value>
</list>
</property>
</bean>
如果 这样配置访问 controller 返回string 类型的 方法
就可以通过 debug 日志看到 例如 :
RequestResponseBodyMethodProcessor.writeWithMessageConverters(150) | Written [{"a":"aa哈哈"}] as "text/html" using [org.springframework.http.converter.StringHttpMessageConverter@20c2
而 这时候
这时候的响应给客户端的响应头 Content-Type 肯定是
Content-Type:text/html;charset=UTF-8
也就是说
supportedMediaTypes 配置的是 StringHttpMessageConverter 响应给客户端的 Content-Type 内容。
这个 StringHttpMessageConverter 源码里面,默认的 supportedMediaTypes 就是 text和 plain
即 <value>text/html</value>
<value>text/plain</value>
其实 这个 supportedMediaTypes 我们可以配置很多种类型的
比如 配置 <value>application/json;charset=UTF-8</value>
springmvc 将 尽量 根据内容 尽量使用 对应的 ,正确的 Content-Type
比如 只配置了 <value>application/json;charset=UTF-8</value>
那么 Content-Type 就是 application/json;charset=UTF-8
是不会 报错的。
第二 种解决中文乱码
StringHttpMessageConverter 配置 构造方法没有指定 字符集而是 supportedMediaTypes 指定字符集
<property name="supportedMediaTypes">
<list>
<value>text/plain; charset=UTF-8</value>
<value>text/html; charset=UTF-8</value>
</list>
</property>
那么 StringHttpMessageConverter 就会根据 supportedMediaTypes 里面的 charset 来使用 响应的字符集,
也就是 这样也是可以防止乱码的。
第三 返回json 对象或者对象不乱码?
比如配置了
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
</bean>
也就是 说将使用其处理 所有的类型,
假如没有配置 StringHttpMessageConverter
那么 string类型的返回controller 方法 最终也是会使用 MappingJacksonHttpMessageConverter 进行处理的,
只是 contentype 将是 application/json;charset=UTF-8
如果配置 StringHttpMessageConverter 了,那么string类型的 返回方法将使用 StringHttpMessageConverter 来处理,
从 名字就可以看出来了。
MappingJacksonHttpMessageConverter 处理过的 响应头部都是 application/json;charset=UTF-8
因为
MappingJacksonHttpMessageConverter 源码默认指定了 默认字符集 UTF-8所以我们配置的时候不需要指定 字符集了,不会乱码的