问题背景

  本文并不是介绍@ResponseBody注解,也不是中文乱码问题的大汇总笔记,这些网上都有很多内容了。这边仅对几年前,一个卡壳了挺久时间的问题的解决过程做一个记录,以警惕自己,达到自醒得目的。  

  @ReponseBody 注解不用多介绍了,用过SpringMVC的同学都很熟了,@ResponseBody 将内容或对象作为 HTTP 响应正文返回,使用@ResponseBody将会跳过视图处理部分,而是调用适合的HttpMessageConverter,将返回值写入输出流。在日常工作中,通常使用封装好的ViewModel进行后台数据的返回,一切正常。但一次在使用@ReponseBody进行返回String数据的时候,竟会出现中文乱码。

  编程的过程免不了遇到各种问题,而遇到问题然后解决问题的这个过程我认为是最让人兴奋的事情。越棘手的问题,解决以后带来的快感也越大(PS:当然解决不了的话,就会越烦躁。。),还是言归正传,谈一下解决错误的过程。

问题分析

  最早我一直以为Spring配置一下编码过滤器就可以解决任何中文乱码问题,代码如下: 恩,确实一直是这样设置着,然并卵。

<filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

  直接返回String会乱码,而返回ViewModel的那个不会乱码,这是为什么?

  其实也可以说是SpringMVC的一个bug,SpringMVC有一系列HttpMessageConverter去处理用@ResponseBody注解的返回值,如返回VM则使用MappingJacksonHttpMessageConverter,若返回String,则使用StringHttpMessageConverter,这个convert使用的是字符集是iso-8859-1,而且是final的,如下:

public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); 

  既然是String有问题,那自然就直接从适配器AnnotationMethodHandlerAdapter 的字符串解析器 StringHttpMessageConverter 入手,设置编码类型即可?

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.StringHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value></list></property></bean>
...

  NO!

那万金油response.setContentType("text/html; charset=UTF-8");呢?NO!

  那么重写StringHttpMessageConverter应该可以了吗?NO!

  上面方法都不行,就尝试着各种百度,说法多种多样,但答案还是:NO!

问题解决

  恩,看来我们得从源头开始再理一遍,既然问题在解析器,那么可以从配置文件配置解析器的配置文件入手。mvc-config.xml 文件从上到下:控制层扫描、国际化配置、文件上传表单解析器、自定义拦截器、视图配置。好像都不是,继续往下,一些HandlerMapping和HandlerAdapter,还有一句<mvc:annotation-driven/>。

  网上查阅了一下资料,果然发现问题其实就在这句<mvc:annotation-driven/>。

  <mvc:annotation-driven /> 是一种简写模式,它会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的,并且提供了其他一些支持。。。略

  上面使用为StringHttpMessageConverter设置编码模式其实正常是有效的,但是在使用了<mvc:annotation-driven />语句后,再次显示声明其他bean,可能就无效了。

<mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg value="UTF-8"/></bean></mvc:message-converters></mvc:annotation-driven>

扩展:其他解决方案

  除了使用上面那种方案之外,还可以使用下面的: 

  1、完全不使用String返回,直接都通过统一的ViewModel去返回,如ResultModel等(正常也是这么干的,总还要错误信息等吧);
  2、通过@RequestMapping的属性处理,该注解的属性produces用于指定返回的内容类型,这算肯定可以了,代码如下:

@RequestMapping(value="/test", method=RequestMethod.POST, produces="text/html;charset=UTF-8")

  注意:既然使用了配置<mvc:annotation-driven>,还是建议在该配置内部进行处理。

编后语

   上面的问题记录是很多多年前的了,现在翻到博客上,只是为了告诫自己:

  天下文章一大抄,但是抄来抄去,不管是写的人,还是看的人,自己最好都能理解或者亲自去尝试一下;这个乱码问题网上总结太多太多了,不能说是错误的,但是又有几个正确得说清楚呢?

  如果放在现在来解决这个问题,最好的方案还是直接跟一下SpringMVC的源码,简单明了。String类型的返回值处理会进入StringHttpMessageConverter解析器,观察getContentTypeCharset方法的参数,可以看到当前解析编码是text/plain;charset=ISO-8859-1,即设置不成功,设置不成功可以继续看看适配器AnnotationMethodHandlerAdapter的属性设置,一层层反推,总会发现问题的。

  这里奉劝各位兄弟姐妹,网上的东西还是要仔细研究的,不要转来转去的。

Spring框架:@ResponseBody 中文乱码----------我的主题站内单点登录的更多相关文章

  1. 解决Spring框架下中文乱码的问题

    在使用了Spring框架下回发现很多表单交互的地方会发生乱码,而且写到数据库中也是乱码,这其实还是字符编码的问题,在我们还在用自己写的servlet的时候,直接在request和response加上字 ...

  2. Hession集成Spring + maven依赖通讯comm项目 + 解决@ResponseBody中文乱码

    hessian结合spring的demo         hessian的maven依赖: <!-- hessian --> <dependency>         < ...

  3. 《经久不衰的Spring框架:@ResponseBody 中文乱码》

    问题背景 本文并不是介绍@ResponseBody注解,也不是中文乱码问题的大汇总笔记,这些网上都有很多内容了.这边仅对几年前,一个卡壳了挺久时间的问题的解决过程做一个记录,以警惕自己,达到自醒得目的 ...

  4. 《经久不衰的Spring框架:@ResponseBody 中文乱码》(转)

    转载自:http://www.cnblogs.com/shanrengo/p/6429291.html 问题背景 本文并不是介绍@ResponseBody注解,也不是中文乱码问题的大汇总笔记,这些网上 ...

  5. Spring Mvc中@ResponseBody中文乱码解决,以及修改返回的Content-Type

    http://www.codeif.com/topic/784 spring 3 mvc 的 @ResponseBody返回数据用起来很方便,但是中文乱码,而且返回的Content-Type不带编码信 ...

  6. easyUI 接收Spring Mvc中@ResponseBody中文乱码解决

    接触springMVC不够深入,乱码困扰我到深夜,特此留下记忆: @responsebody默认滴是ISO-8859-1 Controller注解参数 @ResponseBody 标注后返回Strin ...

  7. SpringMvc返回@ResponseBody中文乱码

    使用SpringMvc的@ResponseBody返回指定数据的类型做为http体向外输出,在浏览器里返回的内容里有中文,会出现乱码,项目的编码.tomcat编码等都已设置成utf-8,如下返回的是一 ...

  8. Spring MVC POST中文乱码解决方案

    spring Web MVC框架提供了org.springframework.web.filter.CharacterEncodingFilter用于解决POST方式造成的中文乱码问题,具体配置如下: ...

  9. 使用SpringMVC框架解决中文乱码的问题

    spring Web MVC框架提供了org.springframework.web.filter.CharacterEncodingFilter用于解决POST方式造成的中文乱码 问题. 需要在we ...

随机推荐

  1. Surface RT2使用情况

    Surface RT2是一个6年的古董了,暂时还能使用的功能包括但不限于一些xbox小游戏,ppt阅读(加载慢),pdf阅读(加载慢),word阅读. 2018/6/16 爱奇艺关闭了大部分win8R ...

  2. Spring中配置使用slf4j + log4j

    本人也是查看别人博客获得的方法,详细讲解请参照 https://www.cnblogs.com/yuxiaole/p/9297266.html 下面进入正题: 1.在pom.xml中注入相关的依赖 & ...

  3. js检测页面离开

    window.location = 'yjk://app.h5.ihaozhuo.com?page=livetrailer&videoLiveId=' + parseInt(this.Requ ...

  4. spring(AOP)静态代理

    姓名:黄于霞      班级:软件151 1.定义抽象主题接口,假设需实现一个计算的类Math.完成加.减.乘.除功能,如下所示: 2.主题类,算术类,实现抽象接口. 3.代理类 4.测试运行 5.总 ...

  5. es6 - 一共有 6 种声明变量的方法(var, function, let, const, class, import)

    var命令和function命令声明的全局变量,依旧是顶层对象的属性:let命令.const命令.class命令声明的全局变量,不属于顶层对象的属性.也就是说,从 ES6 开始,全局变量将逐步与顶层对 ...

  6. django中的Q查询

    转载于:https://mozillazg.com/2015/11/django-the-power-of-q-objects-and-how-to-use-q-object.html 原文写的很详细 ...

  7. 代码规范mark一下

    转自于:https://github.com/zh-google-styleguide/zh-google-styleguide/blob/master/google-python-styleguid ...

  8. maven jstl The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

    maven jstl 报错 HTTP Status 500 – Internal Server Error Type Exception Report Message The absolute uri ...

  9. JS案例六_2:省市级联动

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. my goal

    I want to get a good command of a programming language at the university, and I have to pass the tes ...