spring - 国际化

原创 2015年12月01日 15:10:23

一、国际化

国际化指的是:在web开发(http协议的website/web-service)中,对于不同的语言环境给出相应的语言数据。

基本实现思路:

1. 判断 - 两种方式

  1. 根据Request Headers中的Accept-language来判断。
  2. 要求客户端第一次(也可以每次)传递的自定义参数值来判断,如规定传locale,值为:zh-cn、en-us等等内容。

2. 请求与状态保存

  • WEB应用
    • 后台判断时机
      1. 设置一个专门的”语言切换请求”,对应前端首页右上角弄个切换语言下拉框;
      2. 进入首页时判断一次;
    • 后台状态保存
      1. 在如上的判断时机情况下,把语言标识放入session中,需要国际化数据的请求都去session中取语言标识。
      2. cookie如上,只不过将语言标识放入客户端,然后再每次请求中取值。
        web-service:没办法,只能每次都在请求本身上去判断了。

3. 数据源

  1. 如果数据是可以被管理系统编辑的:将其存入数据库表中,一种语言一个字段。
  2. 如果数据是不变(最多只允许管理员或程序员去手写修改)的:将其存入服务器的静态资源文件中,一种语言一个静态资源文件(java中是properties文件)。

4. 读取

根据请求的判断结果(请求本身/session/cookie),读取不同数据源即可。



二、spring中

1. 首先定义好相应的国际化资源文件:

这里写图片描述

  • 后缀名要按规定写成*_语言码_地区码.properties,值有哪些可以查看java.util.Locale中的定义;
  • 在相应的properties文件中key写一样,value写成不同的语言
messages_en.properties:
error.user.userName.NotBlank = userName Cann't be Blank

messages_zh_CN.properties:
error.user.userName.NotBlank = userName不能为空

2. 配置spring

  • spring-context.jar中提供了一个消息源类org.springframework.context.support.ResourceBundleMessageSource,来容纳properties文件的消息内容,设置其basename属性后,容器就将其指定value前缀的properties文件都加载进这一个messageSource中。
  • spring容器ApplicationContext的所有子类都实现了MessageSource接口,能直接使用容器的方法取出资源中数据。
    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n.messages"/>
    </bean>

3. java实现

  • 当实例化spring容器(context)之后,就可以直接使用容器的方法getMessage(**)来获取对应不同Locale的消息了
        MessageSource messageSource = new ClassPathXmlApplicationContext("spring-context-i18n.xml");
        //ApplicationContext messageSource = new ClassPathXmlApplicationContext("spring-context-i18n.xml");
        String message1 = messageSource.getMessage("error.user.userName.NotBlank", null, Locale.UK);
        //String message2 = messageSource.getMessage("error.user.userName.Length", new Object[]{"10"}, Locale.CHINESE);
        System.out.println(message1);
        //System.out.println(message2);
  • 编码问题
1. 改变properties文件编码为UTF-8/GBK,然后ResourceBundleMessageSource的默认编码defaultEncoding是ISO-8859-1,你可以在xml中增加一个相应属性将其改变为你需要的UTF-8/GBK之类。
2. 如果资源文件想统一使用ISO-8859-1格式也没关系,你可以将原本用UTF-8写好的中文资源文件使用jdk自带的工具native2ascii将UTF-8文件和内容转为ISO-8859-1文件,其中的中文内容会使用16进制unicode编码为\u****格式;
cmd命令:
JAVA_HOME\bin\native2ascii -encoding UTF-8 messages_zh_CN.properties messages_zh_C1N.properties

################## User #####################
error.user.userName.NotBlank = userName不能为空 

                    ↓

################## User #####################
error.user.userName.NotBlank = userName\u4e0d\u80fd\u4e3a\u7a7a


三、spring-mvc中

1. 场景与思路一

场景 :RESTful web service中验证前台传递的参数,如果错误返回国际化错误信息。
1. 定义国际化资源文件messageSource。
2. 使用基于JSR349 Bean Validation 1.1 (老版本JSR303 1.0)的hibernate实现方案,并制定这个validator的messageSource为1中我们定义的。
3. 指定RequestMappingHandlerMapping(支持@Valid)默认使用的validator为2中的。
4. 定义Request DTO,并在其字段上定义校验规则。
5. 在Controller的method上声明使用注解@Valid式验证bean,然后将返回结果绑定在Error(BeanPropertyBindingResult)上。

2. 分解步骤

1. 123xml(properties见二.1)

    <!-- 仅scan所有的@controller -->
    <context:component-scan base-package="com.ddup" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!-- 3 -->
    <mvc:annotation-driven validator="validator"/>
    <!-- 1 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="basename" value="i18n.messages"/>
        <property name="useCodeAsDefaultMessage" value="true" />
    </bean>    
    <!-- 2 -->
    <bean id="validator"  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass"  value="org.hibernate.validator.HibernateValidator"/>
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>

2. DTO

    @NotBlank(message = "{error.user.userName.NotBlank}")
    private String userName;
    get/set...

3. Controller

    @RequestMapping(value = "/login")
    public String login(@Valid TestReq dtoReq, Errors errors){...}

2. 场景与思路二

场景 :验证前台传递的参数,如果错误返回国际化错误信息。
1. 拦截请求,并根据请求或者默认的设置来getMessage返回

分解步骤

1. 拦截请求RequestMappingHandlerMapping

  1. 并不该拦截所有的请求,只应该拦截发布了url的请求(@RequestMapping),所以使用:

    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
            <!-- 拦截器 Interceptors -->
            <property name="interceptors">
                <list>
                    <!-- i18n -->
                    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
                </list>
            </property>
        </bean>

    其中RequestMappingHandlerMapping(请求映射处理器映射)是默认的加载@RequestMapping注解的类。

2. 拦截器LocaleChangeInterceptor

  1. 我们只需要给RequestMappingHandlerMapping配置拦截器LocaleChangeInterceptor,这是一个接口也可括展实现。内容是:

    LocaleChangeInterceptor去请求中找国际化参数(默认为locale)如果找到了,就继续从request的attribute中找到LocalResolver,并setLocale
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws ServletException {
    
            String newLocale = request.getParameter(getParamName());
            if (newLocale != null) {
                if (checkHttpMethod(request.getMethod())) {
                    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                    if (localeResolver == null) {...}
                    try {
                        localeResolver.setLocale(request, response, StringUtils.parseLocaleString(newLocale));
                    }
                    catch (IllegalArgumentException ex) {...}
                }
            }
            return true;
        }

3. Locale解析器LocaleResolver

<bean id="validator"  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass"  value="org.hibernate.validator.HibernateValidator"/>
    <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
    <property name="validationMessageSource" ref="messageSource"/>
</bean>

spring的i18n
2. 对应上面的两种思路,在spring-mvc中分别有几个解析器
- AcceptHeaderLocaleResolver:请求头中的参数
- FixedLocaleResolver:固定的(默认jvm的locale)
- SessionLocaleResolver:设置session方式
- CookieLocaleResolver:设置cookie方式
- AbstractLocaleResolver:当然你也可以继承这个抽象类,来实现自己的个性化国际化需求
2. 步骤:
1. DispatcherServlet收到request后会去找LocaleResolver,如果找到了一个实现类(上面几个)那么就会调用它;
2. 任意一个LocaleResolver中的resolveLocale被调用后,会根据相应策略返回一个Locale对象;

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

SpringMVC 使用验证框架 Bean Validation(上)

对于任何一个应用而言在客户端做的数据有效性验证都不是安全有效的,这时候就要求我们在开发的时候在服务端也对数据的有效性进行验证。 SpringMVC 自身对数据在服务端的校验(Hibernate Val...
  • catoop
  • catoop
  • 2016年04月29日 00:03
  • 22064

springmvc注解开发-validation校验

使用注解的方式进行服务器端的数据校验。 Springmvc使用的是hibernate的校验框架validation(和hibernate没有任何关系) 1、校验思路: 页面提交请求的参数,请求到co...

springboot 使用校验框架validation校验

b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务端校验是不可缺少的。 Spring3支持JSR-303验证框架,JSR...

深入理解spring国际化

假设我们正在开发一个支持多国语言的Web应用程序,要求系统能够根据客户端的系统的语言类型返回对应的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的i18n国际化问题。对...

SpringMVC国际化的工作原理

国际化:页面响应式布局一个页面针对不同的设备进行相应的显示,国际化则是也个页面针对不同的地区/语言进行相应的自适应的显示SpringMVC支持的国际化的三个类: ResourceBundleMess...

SpringMVC国际化探索

选自javaee中的框架技术SpringMVC。 本篇主要介绍国际化方面的一些知识,为国际化的一些实现提供一些思路。 本文根据这张图来介绍SpringMVC实现国际化的过程: 1、根据浏览器...

Spring MVC国际化

本文基于Spring MVC 注解-让Spring跑起来。本文提到的国际化是Spring实现国际化的方案之一。         (1) 在applicationContext.xml中添加以下配置信...
  • geloin
  • geloin
  • 2012年05月09日 14:39
  • 7845

javaSE国际化+springMVC当中的国际化深入理解)

假设我们正在开发一个支持多国语言的Web应用程序,要求系统能够根据客户端的系统的语言类型返回对应的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的i18n国际化问题。对...

java框架之spring(国际化处理)

导入相关jar包: 添加资源配置文件: myMessage_zh_CN.properties myMessage_en_US.properties 配置文件applicat...

浅谈spring框架中集成国际化+velocity

1.在spring配置文件中增加如下配置 classpath:/i18n/messages //资源文件的位置 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:spring - 国际化
举报原因:
原因补充:

(最多只允许输入30个字)