Spring MVC 中的中文编码问题小说一蛤

原来以为 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
public class RequestEncodingInterceptor implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception
    {
        request.setCharacterEncoding("utf-8");
        return true;
    }
    ...
}

然后挂在对应的 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>

搞定!(貌似?)