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

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

简单实现具体步骤如下:

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

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

(以上,祝愉快!)

    

    

SpringMVC 资源国际化实现以及常见问题的更多相关文章

  1. springmvc 资源国际化

    <!-- 关于国际化: 1. 在页面上能够根据浏览器语言设置的情况对文本(不是内容), 时间, 数值进行本地化处理 2. 可以在 bean 中获取国际化资源文件 Locale 对应的消息 3. ...

  2. SpringMVC实现国际化过程中所遇问题

    前言:在利用SpringMVC实现国际化的过程中,看似简单,实则还是遇到了一些小问题,现在笔者对所遇问题总结如下. 注:笔者所用的编辑器为Intellij IEDA 14.1.7版本 1.国际化资源文 ...

  3. 一起学SpringMVC之国际化

    随着网络的发展,在Web开发中,系统的国际化需求已经变得非常的普遍.本文主要讲解SpringMVC框架对多语言的支持,仅供学习分享使用,如有不足之处,还请指正. 什么是国际化? 国际化(interna ...

  4. 游戏UI框架设计(7): 资源国际化技术

    游戏UI框架设计(7) --资源国际化技术 说起"资源国际化"技术,个人认为可以追述到微软Window2000 PC操作系统的发布,在这之前windows98操作系统的开发都是先由 ...

  5. springMVC项目国际化(i18n)实现方法

    SpringMVC项目国际化(i18n)实现方法 按照作息规律,每周五晚必须是分享知识的时间\(^o^)/~,这周讲点儿啥呢,项目需要逼格,咱们国际化吧(* ̄rǒ ̄)~,项目中碰到这类需求的童鞋可能并 ...

  6. Struts第八篇【资源国际化、对比JSP的资源国际化】

    资源国际化 我们在学JSTL标签的时候就涉及到了资源国际化,,,但是呢,在JSP的章节我并没有写博文来讲解怎么弄-.一方面感觉JSP的资源国际化好麻烦,另一方面是感觉用的地方很少-..因此就没有深入去 ...

  7. Android:认识R类、findViewById方法查找组件、@string查找字符、@color查找颜色、@drawable查找图片、@dimen某个组件尺寸定义、项目引入资源国际化

    导入 之前都是断断续续的看了一些于如何使用android开发的文章.资料等,到目前位置很多基础的东西都不清楚,于是去学习了别人的课程,才了认识了R类.findViewById方法查找组件.项目引入资源 ...

  8. Struts2【UI标签、数据回显、资源国际化】

    Struts2UI标签 Sturts2为了简化我们的开发,也为我们提供了UI标签...也就是显示页面的标签..... 但是呢,Struts2是服务端的框架,因此使用页面的标签是需要在服务器端解析然后再 ...

  9. JAVA WEB开发中的资源国际化

    为什么要国际化? 不同国家与地区语言,文化,生活习惯等差异.在数字,时间,语言,货币,日期,百分数等的不同. 两个名词: I18N:即资源国际化,全称为Internationalization,因为首 ...

随机推荐

  1. PHP中单引号双引号使用原则

    PHP中单引号双引号使用原则   1.PHP中尽量用单引号,HTML代码全部用双引号   2.在包含变量的时候,用双引号可以简化操作   3.复杂的情况下用大括号包起来   4 PHP引号还有一个用处 ...

  2. SkipList的实现

    当做笔记记录下来:) 相比于bTree,skiplist占用更多的空间. 而在并发的环境下skiplist会比bTree效率更高. (bTree插入的时候需要rebalance,需要lock比较多的结 ...

  3. (五)Oracle学习笔记—— 视图

    1. 视图简介 视图是虚表,没有具体物理数据,是通过实体表的一种计算映射逻辑.主要就是为了方便和数据安全. 2. 视图作用 简化数据操作:视图可以简化用户处理数据的方式. 着重于特定数据:不必要的数据 ...

  4. iOS开发-使用代码退出应用程序,带动画。

    有时候我们需要使用代码中断程序,如果直接调用exit方法,会使得程序就像是崩溃那样,因此我们应该加上一个动画效果. 例如: AppDelegate *app = [UIApplication shar ...

  5. HDU - 1358 - Period (KMP)

    Period Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  6. 使用caffe 的 python接口测试数据,选定GPU编号

    只需要在python脚本中添加两行代码: caffe.set_device(0) #使用第一块显卡 caffe.set_mode_gpu() #设为gpu模式 这样,就可以在默认显卡被占用(第一块显卡 ...

  7. JDK1.9环境变量配置

    JAVA_HOME C:\Program Files\Java\jdk-9.0.1 JRE_HOME C:\Program Files\Java\jre-9.0.1 PATH .;%JAVA_HOME ...

  8. spring定时任务(@Scheduled注解)cron表达式详解

    cron表达式详解: 一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素. 按顺序依次为 秒(~) 分钟(~) 小时(~) 天(~) 月(~) 星期(~ =SUN 或 SUN,MON,TU ...

  9. linux mysql 5.7.17 编译安装小记

    官方网站中下载源码包: https://dev.mysql.com/downloads/mysql/ 选择下载源码包: 由于官网下载较慢,我选择使用搜狐镜像站进项下载..速度真的快的不是一星半点: 电 ...

  10. FD_CLOEXEC用法及原因_转

    转自:使用FD_CLOEXEC实现close-on-exec,关闭子进程无用文件描述符 我们经常会碰到需要fork子进程的情况,而且子进程很可能会继续exec新的程序.这就不得不提到子进程中无用文件描 ...