资源国际化可以很方便的实现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. mui.fire() 和 mui.trigger()

    导读:添加自定义事件监听操作和标准js事件监听类似,可直接通过window对象添加,通过mui.fire()方法可触发目标窗口的自定义事件 监听自定义事件 添加自定义事件监听操作和标准js事件监听类似 ...

  2. 关于Fragment API版本号兼容问题

    Fragment 是在API 11(android 3.0)被引入的.然而我的应用 的 android:miniSdkVersion  是 API 8,也就是说该应用是兼容旧版本号的.为了可以兼容旧版 ...

  3. (转)java 打印自身代码——真实世界不存在自指

    public class SelfPrint {      public static void main(String args[]) {          char s = 34;         ...

  4. android js 互相调用

    代码地址如下:http://www.demodashi.com/demo/13107.html android js 互相调用 第二版 支持js匿名函数接收 支持js json对象接收 支持js函数返 ...

  5. WP8简单的计算器

    <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinition ...

  6. 关于行内元素之间有空隙的问题,例如span与input之间

    问题如图: 想要的是下面的效果,而却出现上面的效果,解决方法如下: 对于行元素span或者input来说 很多人会用inline-block来显示他们,但是往往发现  中间会留一段小空隙 , 其实这个 ...

  7. AMD 3600+ X2 CPU配合昂达A69T主板超频教程

    本次超频使用电脑硬件配置如下: AMD 3600+ X2 90nm 昂达 A69T HDMI 宇瞻 DDR II 1G 667普条 西数 WD2500KS SATAII  250G 16M 戴尔 普通 ...

  8. unity, 自定义类中使用print

    在unity脚本中自定义c#类,而且不继承MonoBehaviour的话,若还想在其中使用print函数,可以用MonoBehaviour.print(...).

  9. Atitit.upnp SSDP 查找nas的原理与实现java php c#.net c++

    Atitit.upnp SSDP 查找nas的原理与实现java php c#.net c++ 1. 查找nas的原理1 2. 与dlna的关系1 3. 与ssdp的关系1 4. Cling - Ja ...

  10. VLC Web插件的浏览器兼容性

    网页插件实现原理 IE浏览器基于Activex插件来实现,非IE浏览器采用NPAPI来实现,所以,非浏览器需要支持NPAPI来实现. IE浏览器 FF浏览器(版本小于52) 原因从 Firefox 版 ...