Spring MVC中,当DispatcherServlet初始化的时候,会解析一个LocaleResolver接口的实现类,这个实现类就是用来解析国际化的。
一、国际化解析器
Spring MVC中提供了以下四个实现类:
- AcceptHeaderLocaleResolver:spring默认的区域解析器,它通过校验http请求的accept-language头部来解析区域。这个头是由web浏览器根据底层操作系统的区域设置,这个区域无法改变用户的区域,所以只能根据操作系统设置而获取,一般不使用;
- FixedLocaleResolver:使用固定的locale国际化,也是不可修改;
- CookieLocaleResolver:根据cookie数据获取国际化数据,但是如果用户禁止或没有设置cookie,就会根据http头中的accept-language来获取;
- SessionLocaleResolver:根据session进行国际化,即根据用户设置session的变量进行读取,所以它是可变的,也是使用最多的;
为了修改国际化,Spring MVC还提供了一个拦截器-LocaleChangeInterceptor,通过它可以获取参数,然后根据参数来改变区域;
它的配置方式如下:
1、JAVA配置方式
1⃣️配置CookieLocaleResolver
1 /** 2 * 配置CookieLocaleResolver 3 * bean名称必须是localeResolver 4 * 5 * @return 6 */ 7 @Bean(name = "localeResolver") 8 public CookieLocaleResolver initCookieLocaleResolver() { 9 CookieLocaleResolver clr = new CookieLocaleResolver(); 10 // 设置cookie名称 11 clr.setCookieDomain("lang"); 12 // 设置超时秒数 13 clr.setCookieMaxAge(3600); 14 // 默认使用简体中文 15 clr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); 16 return clr; 17 }
2⃣️配置SessionLocaleResolver
1 /** 2 * 配置SessionLocaleResolver 3 * bean名称必须是localeResolver 4 * 5 * @return 6 */ 7 @Bean(name = "localeResolver") 8 public SessionLocaleResolver initSessionLocaleResolver() { 9 SessionLocaleResolver slr = new SessionLocaleResolver(); 10 // 默认使用简体中文 11 slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); 12 return slr; 13 }
2、XML配置方式
1⃣️配置CookieLocaleResolver
1 <!--第一种:配置cookie国际化解析器 --> 2 <bean id="localeResolver" 3 class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> 4 <!-- cookie变量的名称 --> 5 <property name="cookieName" value="lang" /> 6 <!-- cookie超时时间 --> 7 <property name="cookieMaxAge" value="20" /> 8 <!-- 默认使用简体中文 --> 9 <property name="defaultLocale" value="zh_CN" /> 10 </bean>
2⃣️配置SessionLocaleResolver
1 <!--第一种:配置session国际化解析器 --> 2 <bean id="localResolver" 3 class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> 4 因为session有其自身定义的超时时间和编码,所以此处不需要设置 5 <property name="defaultLocale" value="zh_CN" /> 6 </bean>
注意⚠️:
- 不管配置哪种解析器,bean的名称都必须是localeResolver,这是Spring MVC默认的名称,不能修改,否则找不到;
- session有其自定义的超时时间,所以无需配置;
二、国际化文件加载
在实现国际化之前,首先要加载相关的资源文件,即消息源,这个功能由Spring MVC提供的MessageSource接口完成,并且有四个非抽象的实现类:
- StaticMessageSource:静态消息源;
- DelegatingMessageSource:实现的是代理功能;
- ResourceBundleMessageSource:由JDK提供的Bundle实现,只能把文件放置在对应的类路径下,不具备热加载功能,只有重启系统才能重新加载;
- ReloadavleResourceBundleMessageSource:可以把文件放置在任何地方,并且在不重启系统的前提下也能重新加载资源文件,这样就可以在程序运行期修改并重新加载资源文件;
其实在配置国际化解析器之前还要配置消息源,下面介绍如何配置,还是有两种方式:
1、JAVA方式配置消息源
1⃣️配置ResourceBundleMessageSource
1 /** 2 * 配置ResourceBundleMessageSource消息源 3 * bean名称必须为messageSource 4 * 5 * @return 6 */ 7 @Bean(name = "messageSource") 8 public MessageSource initResourceBundleMessageSource() { 9 ResourceBundleMessageSource rbms = new ResourceBundleMessageSource(); 10 rbms.setDefaultEncoding("UTF-8"); 11 rbms.setBasename("msg"); 12 return rbms; 13 }
2⃣️配置ReloadableResourceBundleMessageSource
1 /** 2 * 配置ReloadableResourceBundleMessageSource消息源 3 * bean名称必须为messageSource 4 * 5 * @return 6 */ 7 @Bean(name = "messageSource") 8 public MessageSource initReloadableResourceBundleMessageSource() { 9 ReloadableResourceBundleMessageSource rrbms = new ReloadableResourceBundleMessageSource(); 10 rrbms.setDefaultEncoding("UTF-8"); 11 // 因为是热加载,所以需要加上classpath 12 rrbms.setBasename("classpath:msg"); 13 // 设置刷新的秒数,即多长时间刷新一次 14 rrbms.setCacheSeconds(1800); 15 // 设置刷新的毫秒数 16 rrbms.setCacheMillis(1800000); 17 return rrbms; 18 }
2、XML方式配置消息源
1⃣️配置ResourceBundleMessageSource
1 <!--第一种方式:配置ResourceBundleMessageSource:这种方式只能把资源文件放到指定的路径下,不能热加载,需要重启系统才能加载它 --> 2 <bean id="messageResource" 3 class="org.springframework.context.support.ResourceBundleMessageSource"> 4 <property name="defaultEncoding" value="UTF-8" /> 5 <property name="basename" value="msg" /> 6 </bean>
2⃣️配置ReloadableResourceBundleMessageSource
1 <!--第二种方式:配置ReloadableResourceBundleMessageSource:这种方式只能把资源文件放到任何位置,不需要重启就能加载文件,并且可以设置刷新时间 --> 2 <bean id="messageSource" 3 class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 4 <!-- 默认编码方式 --> 5 <property name="defaultEncoding" value="UTF-8" /> 6 <!-- 资源文件的前缀:多了一个classpath,如果资源文件在一个文件夹下,还要加上文件夹路径,否则报错 --> 7 <property name="basename" value="classpath:message/msg" /> 8 <!-- 刷新时间 --> 9 <property name="cacheSeconds" value="3600" /> 10 </bean>
需要注意以下几点:
- 无论何种方式配置何种消息源,bean的名称必须是messageSource;
- ReloadableResourceBundleMessageSource可以热加载,所以需要配置刷新时间,并且配置资源文件的前缀时需要加classpath,如果资源文件在classpath的某个文件夹下,还需要加上文件夹的名称;
三、配置拦截器
通过请求参数去改变国际化的值时,可以使用Spring提供的拦截器LocaleChangeInterceptor,它继承了HandlerInterceptorAdapter,通过覆盖它的preHandle方法,然后使系统所配置的LocaleResolver实现国际化,这个一般是配置在Spring MVC的配置文件中:
1 <!-- 配置国际化拦截器 --> 2 <mvc:interceptors> 3 <mvc:interceptor> 4 <mvc:mapping path="/**" /> 5 <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> 6 <property name="paramName" value="language" /> 7 </bean> 8 </mvc:interceptor> 9 </mvc:interceptors>
其中:
- <mvc:mapping>的path属性值配置成/**,这样就能拦截所有/请求及其子路径中的请求了;
- 拦截器的属性paramName的值就是url中传过来的参数,如language=zh_CN或language=en_US等;
至此,国际化中所有的配置都已经介绍完毕,下一篇文章将举一个实现过程的例子。