zoukankan      html  css  js  c++  java
  • SpringMVC 资源国际化实现以及常见问题

    资源国际化可以很方便的实现web项目语言的切换,解决了web项目按需显示不同语言界面的问题.

    SpringMVC 的资源国际化基于JDK的java.util.ResourceBundle实现,经过SpringMVC的封装实现起来非常简单:

    简单实现具体步骤如下:

      1.在SpringMVC的配置文件中配置ResourceBundleMessageSource(该类的作用是绑定资源文件,根据Locale值不同,显示不同的语言)

     1     <!-- 资源国际化相关配置 -->
     2     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
     3         <!-- 如果在国际化资源文件中找不到对应代码的信息,就用这个代码作为名称  -->
     4         <property name="useCodeAsDefaultMessage" value="true" />
     5         <!-- 默认编码格式为 utf-8 -->
     6         <property name="defaultEncoding" value="UTF-8" />
     7         <!-- 国际化信息所在的文件名 --> 
     8         <property name="basenames">                    
     9             <list>
    10                 <value>i18n.messages</value>
    11             </list>
    12         </property>
    13     </bean>

               (PS:basenames属性,值为资源文件的地址)

      2.配置LocaleResolver(该类指明了Locale应该存放在何处)

        LocaleResolver有三种选择,分别是基于request,基于session,基于cookie,因为基于request的实现不支持手动切换,建议使用基于session的实现

        三种方式的配置具体如下:

         a.基于request的实现:

        <!-- 基于request实现资源国际化 -->
        <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" />

                      b.基于session的实现:

        
        <!-- 基于Session实现资源国际化 -->
        <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
            <property name="defaultLocale" value="en"/>
        </bean>

           c.基于cookie的实现

        <!-- 基于cookie实现资源国际化 -->
        <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
            <property name="defaultLocale" value="en"/>
        </bean>

      3.配置localeChangeInterceptor拦截器(该类的作用是根绝不同的LocaleResolve采用不同的方式设置Locale)

        <mvc:interceptors>
            <bean id="localeChangeInterceptor"
                class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
                <property name="paramName" value="langType" />
            </bean>
        </mvc:interceptors>

      (paramName属性,是指请求中 切换语言的参数名)

      4.编写资源文件

        资源文件的命名规则是 basename [ _language ] [ _country ] [ _variant ].properties 

        languange country variant  需要为Locale类中的值

      5.页面获取资源文件中的值(以jsp为例)

    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    
    <spring:message code="comment.management" /> <!-- code的值为资源文件中对应的key -->

            6.页面切换语言

          这种方式实现的资源国际化,会拦截所有的请求,只要请求中带有 localeChangeInterceptor 中定义的参数,拦截器就会修改存储的Locale,实现语言的切换

    常见问题(重点):

      1.基于session不使用拦截器实现

        a.查看LocaleChangeInterceptor源码,逻辑很简单就是看看请求中是否有语言类型的参数,如果有新建一个Locale,然后从request中取出一个LocaleResolver ,然后执行setLocale()方法,

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws ServletException {
    
            String newLocale = request.getParameter(this.paramName);
            if (newLocale != null) {
                LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                if (localeResolver == null) {
                    throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
                }
                localeResolver.setLocale(request, response, StringUtils.parseLocaleString(newLocale));
            }
            // Proceed in any case.
            return true;
        }

        b.查看源码,逻辑也很简单就是将Locale属性放到session中而已

        public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
            WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);
        }

        c.看到这里相信大伙应该心里有数啦,只要我们自己写一个Controller,然后根据我们自定义的参数,自己生成Locale主动放入session中即可,这样就可以去掉配置的拦截器

        @RequestMapping(value = "/changeLanguage", method = RequestMethod.POST)
        public @ResponseBody Language changeLanguage(HttpServletRequest request,
                @RequestParam(value = "langType", defaultValue = "zh") String langType) {
    
            // 获取语言类型
            Language language = Language.getLanguage(langType);
            // 设置语言并放入session中
            Locale locale = new Locale(language.getLanguage(), language.getCountry());
            request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
    
            return language;
        }

      2.资源文件的加载顺序

        a.不得不说这是一个比较坑的问题,首先看现象吧

          配置如下文件: 

            messages_en.properties 

            messages.properties 这里默认是中文

          当运行在中文环境下,切换按钮没有问题,语言可以正常的切换,

          当运行在英文环境下,切换按钮失效,怎么点都是英文,此时我满脸蒙蔽。

        b.问题原因,好吧,既然有问题就只能继续研究呗,最后发现资源文件的加载顺序如下:  


          baseName _ 指定的language _ 指定的country_ 指定的variant

          baseName _ 指定的language _ 指定的country

          baseName _ 指定的language

          baseName _默认的language _默认的country_默认的variant

          baseName _默认的language _默认的country

          baseName_默认的language

          baseName

          我们可以看出,加载顺序为: 

          优先加载指定国际化内容,之后加载默认国际化内容,最后加载顶级文件

        c.解决方法在springMVC中配置LocaleResolve的时候指定默认语言(基于session,基于cookie)

        <!-- 基于cookie实现资源国际化 -->
        <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
            <property name="defaultLocale" value="en"/>
        </bean>

     

    (以上,祝愉快!)

        

        

  • 相关阅读:
    Linq调试实时输出信息扩展方法(摘抄)
    RSA签名和验证数据
    Vue+abp微信扫码登录
    vue学习笔记4
    icon共享网站 可以获得wpf里用的Geometry
    wpf 父控件和子控件 各自触发鼠标按下事件
    C# Timespan Tostring 时分秒格式
    新公司第二天
    C# 反转单向链表
    经纬度转数字经纬度时,如果是负数
  • 原文地址:https://www.cnblogs.com/LionheartCGJ/p/7819688.html
Copyright © 2011-2022 走看看