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国际化,基于数据库的信息配置的主要内容,如果未能解决你的问题,请参考以下文章