之前在做spring国际化的时候,资源文件都是写在properties里面,管理起来不是很方便,今天我将这些资源文件都保存在数据库中,启动的时候进行初始化操作,从而进行多语言的管理。这里记录下过程:
其他的操作还是跟之前一样,这里就不多解释了,直接贴上对应的配置或者代码信息。使用spring框架,我这里用了两个配置文件,一个是springmvc.xm,另一个是spring-framework.xml文件,主要是想分开进行配置。
国际化配置在spring-webmvc这个jar的org.springframework.web.servlet.i18n包下面,这里我采用SessionLocaleResolver来对Locale进行处理,当前你还可以将Locale保存到Cookie中,spring为我们提供了几种实现。
配置如下:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
注意,这里一定要指定一个id,不然spring会去找他默认的,而不是你这个bean。
我们拦截用户的请求,如果用户变更了locale,那么我们也需要对应修改session中的locale数据,这里需要配置一个bean来拦截用户的请求,org.springframework.web.servlet.i18n.LocaleChangeInterceptor
<mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="Lang"/> </bean> </mvc:interceptors>
这样当用户在请求的时候,如果添加了参数Lang=xxx ,那么这个bean就会自动帮我们切换locale信息,从而改变当前的语言信息。我这里为了控制我指定的几种语言,所以我重新写了一个拦截器,内容跟它差不多,只是多了一个判断信息:
package com.jacksoft.iconsole.bootstrap; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.beans.propertyeditors.LocaleEditor; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import org.springframework.web.servlet.support.RequestContextUtils; import com.jacksoft.iconsole.utils.LanguageType; public class MyLocaleChangeInterceptor extends HandlerInterceptorAdapter{ /** * define logger for this class */ private static Logger logger = Logger.getLogger(MyLocaleChangeInterceptor.class); /** * Default name of the locale specification parameter: "locale". */ public static final String DEFAULT_PARAM_NAME = "locale"; private String paramName = DEFAULT_PARAM_NAME; /** * Set the name of the parameter that contains a locale specification * in a locale change request. Default is "locale". */ public void setParamName(String paramName) { this.paramName = paramName; } /** * Return the name of the parameter that contains a locale specification * in a locale change request. */ public String getParamName() { return this.paramName; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String newLocale = request.getParameter(this.paramName); if (newLocale != null) { if(!LanguageType.checkLanguageType(newLocale)){ if(logger.isDebugEnabled()){ logger.debug(" current parameter " + this.paramName + " is not correct,use last local to display language"); } return true; } LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?"); } LocaleEditor localeEditor = new LocaleEditor(); localeEditor.setAsText(newLocale); localeResolver.setLocale(request, response, (Locale) localeEditor.getValue()); } // Proceed in any case. return true; } }
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,这里先贴上代码:
package com.jacksoft.iconsole.bootstrap; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.annotation.PostConstruct; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.ResourceBundleMessageSource; import com.jacksoft.spring.generator.dao.LanguageMapper; import com.jacksoft.spring.generator.model.Language; import com.jacksoft.spring.generator.model.LanguageExample; /** * 从数据库加载多语言来进行显示 * * * @Filename ResourceBundleMessageSourceFromDB.java * * @author Jack.Zhou * * @Date 2013-11-8 * */ public class ResourceBundleMessageSourceFromDB extends ResourceBundleMessageSource { @Autowired private LanguageMapper languageMapper; private static Logger log = Logger.getLogger(ResourceBundleMessageSourceFromDB.class); private static LanguageMapper staticLanguageMapper; /** * store language * zh_cnCode,Test */ private static Map<String,String> langMap = new HashMap<String,String>(); public static void init(){ LanguageExample example = new LanguageExample(); List<Language> list = staticLanguageMapper.selectByExample(example); if(list == null || list.isEmpty()){ log.warn("There is no language message ,please check...."); }else{ for(Language lang : list){ if(log.isDebugEnabled()){ log.debug("load language code:" + lang.getLangCode() + " translate " + lang.getLang() + " is " + lang.getLangName()); } langMap.put(lang.getLang().toLowerCase() + lang.getLangCode(), lang.getLangName()); } } } @PostConstruct public void initMethod(){ log.info("copy langaugeMapper to local static ver"); staticLanguageMapper = languageMapper; init(); } @Override protected String getMessageInternal(String code, Object[] args, Locale locale) { if(log.isDebugEnabled()){ log.debug("The code is:" + code + " and locale is :" + locale.toLanguageTag()); } String localName = locale.toString().toLowerCase(); String message = langMap.get(localName + code); if(message != null){ for(int i = 0;args != null && i<args.length;i++){ message = message.replace("{"+i+"}", args[i].toString()); } }else if(isUseCodeAsDefaultMessage()){ message = code; if(log.isDebugEnabled()){ log.debug("No message found under code [" + code + "] for local [" + localName + "] and use code to display" ); } }else{ message = null; if(log.isDebugEnabled()){ log.debug("No message found under code [" + code + "] for local [" + localName + "] " ); } } return message; } /** * 根据code和locale来获取多语言信息 * @param code * @param locale * @return */ public static String getMessage(String code,Locale locale){ String localName = locale.toString().toLowerCase(); String message = langMap.get(localName + code); if(message == null){ message = code; if(log.isDebugEnabled()){ log.debug("No message found under code [" + code + "] for local [" + localName + "]" ); } } return message; } }
因为我使用的是mybatis,而为了让spring给静态属性注入数据,我这里加了个initMethod方法,通过注解@PostConstruct来完成调用,注意,该注解是要在实例化之后才调用的,让这个方法来为我的静态属性进行赋值操作,然后在init方法中将多语言查询出来,存放到map中保存起来。
通过重写getMessageInternal方法,就可以根据Local和code去刚才的map中获取对应的数据信息,该方法有三个参数,分别是
code:对应多语言的code,
args:在显示多语言时,添加的参数,这里我定义了格式为: {0}这样的替换方式,
locale:本地语言
这样将获取到的message返回,就可以了。
然后在将这个bean配置到spring来管理:
<bean id="messageSource" class="com.jacksoft.iconsole.bootstrap.ResourceBundleMessageSourceFromDB"> <property name="useCodeAsDefaultMessage" value="true"></property> </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来进行切换试试~
相关推荐
在本项目"spring国际化项目"中,我们将深入探讨如何在Spring环境中实现国际化。 首先,我们需要理解国际化的基本概念。国际化不仅仅是翻译文本,它涉及将应用程序中的所有文化特定元素,如日期格式、货币符号、数字...
Spring框架是Java开发中的一个核心库,它提供了一个广泛的功能集,包括依赖注入、面向切面编程、数据访问、Web应用程序开发以及我们今天关注的主题——国际化(i18n)。国际化是一个过程,使得软件能够适应不同语言...
在Spring框架中,国际化(Internationalization,简称i18n)是为支持多语言环境而设计的功能,使得应用程序能够根据用户的地区或语言设置提供相应的显示内容。本案例将深入探讨如何在Spring应用中实现国际化。 首先...
Spring MVC 国际化实现详解 在 Spring MVC 框架中,实现国际化是一项非常重要的任务。国际化可以让我们的应用程序适应不同语言和地区,提高应用程序的可读性和可用性。本文将详细介绍如何使用 Spring MVC 实现国际...
标题 "spring国际化jsp" 暗示我们讨论的是在Spring框架中实现Web应用程序的国际化(i18n)过程,特别是在使用JSP(JavaServer Pages)时。这通常涉及到资源包(properties文件)的使用,以存储不同语言的文本字符串...
Spring 国际化(i18n)是Spring框架中用于支持多语言环境的功能,它使得应用程序能够根据用户的地域设置显示相应的语言内容。在本文中,我们将深入探讨Spring的国际化实现,包括其工作原理、配置步骤以及实际应用。 ...
Spring国际化Demo
Spring国际化Demo.zip
而Spring的国际化(i18n,Internationalization)功能则允许我们为不同地区和语言的用户提供定制的显示内容。 在Spring MVC中实现国际化,主要涉及以下几个关键步骤和概念: 1. **资源文件**:首先,我们需要创建...
在Spring框架中,国际化(Internationalization,简称i18n)是为支持多语言环境而设计的功能,使得应用程序能够根据用户所在的地域和语言提供相应的显示内容。本示例将详细介绍如何在Spring应用中实现国际化。 首先...
解决Spring国际化文案占位符失效问题的方法 Spring国际化文案占位符是指在Spring框架中使用MessageSource来处理国际化文案,但是有时候占位符可能不会被正确地替换,导致文案显示不正确。这种情况下,需要了解...
在Spring框架中,实现国际化(Internationalization,简称i18n)是常见的需求,它使得应用程序可以根据用户所在的地区提供不同的语言版本。以下是一个详细的步骤,解释如何在Spring应用中实现国际化。 1. **理解...
Spring和其它的框架一样,也提供了国际化功能,它是通过MessageSource接口来实现的 ApplicationContext接口继承了MessageSource 。 MessageSource接口方法
在Spring MVC 3中,国际化是一项重要的功能,它允许我们为不同的地区和语言提供定制的显示内容。在“spring mvc 3 国际化(下)——简单自定义操作”这一主题中,我们将深入探讨如何自定义国际化过程,以满足特定的...
Spring MVC的国际化(Internationalization)指的是将应用根据不同地域、语言习惯以及文化差异进行本地化的过程。这涉及了软件应用对多语言的支持,以便不同区域的用户能够以自己的母语使用软件。Spring MVC提供了...
在这个"SpringBoot国际化.zip"压缩包中,我们看到与Spring Boot项目相关的各种文件,这表明该压缩包可能包含一个实现Spring Boot应用国际化的示例。让我们详细探讨一下Spring Boot如何实现国际化,以及相关文件的...
spring2国际化的demo 用的是eclipse+myeclipse6.0GA 很简单 但是感觉不错 学习之后留着备用 里面加入用到了spring的泛型工厂 可以不用强制转换了
关于spring国际化的详细例子,很经典,一看便会!
Spring Boot的国际化(i18n)配置是其强大功能的一部分,它允许开发人员为不同地区的用户提供本地化的应用体验。这个“Spring Boot 国际化(i18n)配置demo.zip”包含了一个演示如何在Spring Boot项目中实现i18n的示例...