原来以为 Java 中文支持的会很好,没想到一用 Spring 就出乱码啦,看来人家默认情况下都不吊你第三世界国家的。。。
anyway 切入正题,我股沟了一下相关的内容,发现大多数解决方法都是加个 servlet filter 来转换编码。觉得这方法不好,好像虽然有用但是比较糊弄事,不彻底明白始终不爽。所以我就在源代码里游啊游,整理出大概的思路,如下:
页面显示中文
这部分以 jsp 为例, Spring MVC 在 resolve 页面显示的时候是这么一个流程。
InternalResourceViewResolver 利用 InternalResourceView 来 build view。 InternalResourceView 则会将最终页面生成的请求转交给对应的 jsp 来通过 container 实现。
如果页面显示有乱码,问题貌似会出在 InternalResourceView 上,实际上 InternalResourceViewResolver 的父类中有一个叫 UrlBasedViewResolver 的东东,里面有个属性叫做 contentType,并且会在 buid view 的时候最终把这个属性赋值给 InternalResourceView 。貌似找到了问题的原因。我试着这样设置并窃喜:
1 2 3 4 5 | <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="contentType" value="utf-8"></property> ... </bean> |
页面刷新后乱码依旧。。。回到源文件中,游啊游,发现其实 InternalResourceViewResolver 虽然有给 InternalResourceView 赋值 contentType,但是 InternalResourceView 忽视了这个属性。。。然后直接转交给对应的 jsp 处理。看来问题实际上出在 jsp 上。到对应的 jsp 页面,加上下面的代码:
1 | <%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%> |
然后在编辑器里确保源文件也存成 utf-8,然后刷新页面,好了。
h3. 提交中文参数
原以为这样就 OK 了,后来发现还没完。。。在表单提交的时候,中文依然乱码,sun。再游! 发现要改的地方有两点,第一个是针对表单的 POST,因为默认的 request body 处理的编码不是 utf-8 所以在 decode body 的时候会解出乱码来。这需要写个Interceptor 来设置 request 的 encoding ,比如:
1 2 3 4 5 6 7 8 9 10 11 |
然后挂在对应的 handlerMapping 上面,比如:
1 2 3 4 5 6 7 8 9 | <bean id="handlerMapping"> class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <bean class="RequestEncodingInterceptor"> </list> </property> ... </bean> |
另一方面,如果 url get 中有 encode 之后的中文参数,还需要确保 url decode 也用 utf-8 来解。由于 BeanNameUrlHandlerMapping 通过 UrlPathHelper 来处理 url,所以需要这样配置:
1 2 3 4 5 6 7 8 9 10 | <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> .... <property name="urlPathHelper"> <bean class="org.springframework.web.util.UrlPathHelper"> <property name="urlDecode" value="true"></property> <property name="defaultEncoding" value="utf-8"></property> </bean> </property> </bean> |
国际化 i18n
国际化的配置文件如果用 java 的 properties 文件是不支持 utf-8 滴,要换成 Spring 的 ReloadableResourceBundleMessageSource ,酱紫配置:
1 2 3 4 5 | <bean id="messageSource"> class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="WEB-INF/i18n/messages"></property> <property name="defaultEncoding" value="utf-8"></property> </bean> |
搞定!(貌似?)
