spring国际化,基于数据库的信息配置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring国际化,基于数据库的信息配置相关的知识,希望对你有一定的参考价值。

  之前在做spring国际化的时候,资源文件都是写在properties里面,管理起来不是很方便,今天我将这些资源文件都保存在数据库中,启动的时候进行初始化操作,从而进行多语言的管理。这里记录下过程:

    其他的操作还是跟之前一样,这里就不多解释了,直接贴上对应的配置或者代码信息。使用spring框架,我这里用了两个配置文件,一个是springmvc.xm,另一个是spring-framework.xml文件,主要是想分开进行配置。

国际化配置在spring-webmvc这个jar的org.springframework.web.servlet.i18n包下面,这里我采用SessionLocaleResolver来对Locale进行处理,当前你还可以将Locale保存到Cookie中,spring为我们提供了几种实现。

配置如下:

1 <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>

 

注意,这里一定要指定一个id,不然spring会去找他默认的,而不是你这个bean。

 我们拦截用户的请求,如果用户变更了locale,那么我们也需要对应修改session中的locale数据,这里需要配置一个bean来拦截用户的请求,org.springframework.web.servlet.i18n.LocaleChangeInterceptor

1     <mvc:interceptors>
2         <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
3             <property name="paramName" value="Lang"/>
4         </bean>
5     </mvc:interceptors>

 

 这样当用户在请求的时候,如果添加了参数Lang=xxx ,那么这个bean就会自动帮我们切换locale信息,从而改变当前的语言信息。我这里为了控制我指定的几种语言,所以我重新写了一个拦截器,内容跟它差不多,只是多了一个判断信息。

 1 package com.jacksoft.iconsole.bootstrap;
 2 
 3 import java.util.Locale;
 4 
 5 import javax.servlet.http.HttpServletRequest;
 6 import javax.servlet.http.HttpServletResponse;
 7 
 8 import org.apache.log4j.Logger;
 9 import org.springframework.beans.propertyeditors.LocaleEditor;
10 import org.springframework.web.servlet.LocaleResolver;
11 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
12 import org.springframework.web.servlet.support.RequestContextUtils;
13 
14 import com.jacksoft.iconsole.utils.LanguageType;
15 
16 public class MyLocaleChangeInterceptor extends HandlerInterceptorAdapter{
17 
18     /**
19      *  define logger for this class
20      */
21     private static Logger logger = Logger.getLogger(MyLocaleChangeInterceptor.class);
22 
23     /**
24      * Default name of the locale specification parameter: "locale".
25      */
26     public static final String DEFAULT_PARAM_NAME = "locale";
27 
28     private String paramName = DEFAULT_PARAM_NAME;
29     
30     
31     /**
32      * Set the name of the parameter that contains a locale specification
33      * in a locale change request. Default is "locale".
34      */
35     public void setParamName(String paramName) {
36         this.paramName = paramName;
37     }
38 
39     /**
40      * Return the name of the parameter that contains a locale specification
41      * in a locale change request.
42      */
43     public String getParamName() {
44         return this.paramName;
45     }
46     
47     
48     @Override
49     public boolean preHandle(HttpServletRequest request,
50             HttpServletResponse response, Object handler) throws Exception {
51         String newLocale = request.getParameter(this.paramName);
52         if (newLocale != null) {
53             
54             if(!LanguageType.checkLanguageType(newLocale)){
55                 if(logger.isDebugEnabled()){
56                     logger.debug(" current parameter " + this.paramName + " is not correct,use last local to display language");
57                 }
58                 return true;
59             }
60             
61             LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
62             if (localeResolver == null) {
63                 throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
64             }
65             LocaleEditor localeEditor = new LocaleEditor();
66             localeEditor.setAsText(newLocale);
67             localeResolver.setLocale(request, response, (Locale) localeEditor.getValue());
68         }
69         // Proceed in any case.
70         return true;
71     }
72 
73 }

 

 

 LanguageType:

package com.jacksoft.iconsole.utils;

/**
 *  多语言
 * 
 *
 * @Filename LanguageType.java
 *
 * @author Jack.Zhou
 *
 * @Date 2013-11-8
 *
 */
public enum LanguageType {

    en_US,zh_CN;
    
    public static boolean checkLanguageType(String languageCode){
        for(LanguageType lang : LanguageType.values()){
            if(lang.name().equals(languageCode)){
                return true;
            }
        }
        return false;
    }
}

 

 这样就可以指定语言的种类了,如果输入其他的语言,比如zh_TW,那么系统还是默认使用当前的语言,并不会进行修改操作。

 

 接下来就是配置ResourceBundleMessageSource了,因为我们需要解析语言,为了能从数据库获取语言信息,我单独写了个类ResourceBundleMessageSourceFromDB来集成ResourceBundleMessageSource,这里先贴上代码:

 

  1 package com.jacksoft.iconsole.bootstrap;
  2 
  3 import java.util.HashMap;
  4 import java.util.List;
  5 import java.util.Locale;
  6 import java.util.Map;
  7 
  8 import javax.annotation.PostConstruct;
  9 
 10 
 11 import org.apache.log4j.Logger;
 12 import org.springframework.beans.factory.annotation.Autowired;
 13 import org.springframework.context.support.ResourceBundleMessageSource;
 14 
 15 import com.jacksoft.spring.generator.dao.LanguageMapper;
 16 import com.jacksoft.spring.generator.model.Language;
 17 import com.jacksoft.spring.generator.model.LanguageExample;
 18 
 19 /**
 20  *   从数据库加载多语言来进行显示
 21  * 
 22  *
 23  * @Filename ResourceBundleMessageSourceFromDB.java
 24  *
 25  * @author Jack.Zhou
 26  *
 27  * @Date 2013-11-8
 28  *
 29  */
 30 public class ResourceBundleMessageSourceFromDB extends
 31         ResourceBundleMessageSource {
 32 
 33     @Autowired
 34     private LanguageMapper languageMapper;
 35     
 36     
 37     private static Logger log = Logger.getLogger(ResourceBundleMessageSourceFromDB.class);
 38     
 39     private static LanguageMapper staticLanguageMapper;
 40     /**
 41      *  store language
 42      *  zh_cnCode,Test
 43      */
 44     private static Map<String,String> langMap = new HashMap<String,String>();
 45     
 46     
 47     public static void init(){
 48         LanguageExample example = new LanguageExample();
 49         List<Language> list = staticLanguageMapper.selectByExample(example);
 50         if(list == null || list.isEmpty()){
 51             log.warn("There is no language message ,please check....");
 52         }else{
 53             for(Language lang : list){
 54                 if(log.isDebugEnabled()){
 55                     log.debug("load language code:" + lang.getLangCode()
 56                             + "  translate " + lang.getLang() + "  is  "
 57                             + lang.getLangName());
 58                 }
 59                 langMap.put(lang.getLang().toLowerCase() + lang.getLangCode(), lang.getLangName());
 60             }
 61         }
 62     }
 63     
 64     @PostConstruct
 65     public void initMethod(){
 66         log.info("copy langaugeMapper to local static ver");
 67         staticLanguageMapper = languageMapper;
 68         init();
 69     }
 70 
 71     @Override
 72     protected String getMessageInternal(String code, Object[] args,
 73             Locale locale) {
 74         if(log.isDebugEnabled()){
 75             log.debug("The code is:" + code + " and locale is :" + locale.toLanguageTag());
 76         }
 77         String localName = locale.toString().toLowerCase();
 78         String message = langMap.get(localName + code);
 79         if(message != null){
 80             for(int i = 0;args != null && i<args.length;i++){
 81                 message = message.replace("{"+i+"}", args[i].toString());
 82             }
 83         }else if(isUseCodeAsDefaultMessage()){
 84             message = code;
 85             if(log.isDebugEnabled()){
 86                 log.debug("No message found under code  [" + code + "] for local [" + localName + "] and use code to display" );
 87             }
 88         }else{
 89             message = null;
 90             if(log.isDebugEnabled()){
 91                 log.debug("No message found under code  [" + code + "] for local [" + localName + "] " );
 92             }
 93         }
 94         
 95         return message;
 96     }
 97     
 98     /**
 99      *  根据code和locale来获取多语言信息
100      * @param code
101      * @param locale
102      * @return
103      */
104     public static String getMessage(String code,Locale locale){
105         String localName = locale.toString().toLowerCase();
106         String message = langMap.get(localName + code);
107         if(message == null){
108             message = code;
109             if(log.isDebugEnabled()){
110                 log.debug("No message found under code  [" + code + "] for local [" + localName + "]" );
111             }
112         }
113         return message;
114     }
115     
116 }

 

因为我使用的是mybatis,而为了让spring给静态属性注入数据,我这里加了个initMethod方法,通过注解@PostConstruct来完成调用,注意,该注解是要在实例化之后才调用的,让这个方法来为我的静态属性进行赋值操作,然后在init方法中将多语言查询出来,存放到map中保存起来。

通过重写getMessageInternal方法,就可以根据Local和code去刚才的map中获取对应的数据信息,该方法有三个参数,分别是

code:对应多语言的code,

args:在显示多语言时,添加的参数,这里我定义了格式为: {0}这样的替换方式,

locale:本地语言

这样将获取到的message返回,就可以了。

然后在将这个bean配置到spring来管理:

 

1     <bean id="messageSource" class="com.jacksoft.iconsole.bootstrap.ResourceBundleMessageSourceFromDB">
2         <property name="useCodeAsDefaultMessage" value="true"></property>
3     </bean>

 

 这里我配置了一个参数:useCodeAsDefaultMessage

在代码中也有体现,就是当找不到code的时候,是否直接输出code

 

最后在jsp中写上测试信息

<spring:message code="TEST"></spring:message>  

 

 

当然还需要引入spring的标签库

<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>  

 

然后启动测试吧~

可以通过添加参数Lang=zh_CN  或者en_US来进行切换试试~

 

 

原文转载自:http://mybar.iteye.com/blog/1973061

以上是关于spring国际化,基于数据库的信息配置的主要内容,如果未能解决你的问题,请参考以下文章

Spring_国际化信息设置

Spring security实现国际化问题

spring国际化locale的代码原理以及拓展配置

spring国际化locale的代码原理以及拓展配置

SpringMVC学习系列 之 国际化

Spring validation中自定义的校验错误提示信息如何支持国际化