SpringMVC(一) 国际化实现及原理

     很多网站的用户分布在世界各地,因此网站需要针对不同国家的用户展示不同语言的内容,因此就有了国际化实现的需求,大多数网站都会在网站的头部或尾部设置语言切换链接,这样就可以直接切换成相应的内容。

国际化实现步骤

1.基于不同的语言定义多个properties文件,用于后面根据本地化信息从相应的properties文件中获取数据。

这里我实现的是简体中文和英文的切换,所以定义了两个properties文件,这两个文件均在根目录下


language_en_US.properties

language.cn = \u4e2d\u6587
language.en = English
internationalisation = \u0020Internationalisation
welcome = This is the English environment
introduce= This is I18N Demo 

language_zh_CN.properties

language.cn = \u4e2d\u6587
language.en = English
internationalisation = \u56fd\u9645\u5316
welcome = \u8fd9\u662f\u4e2d\u6587\u73af\u5883
introduce= \u8fd9\u662f\u56fd\u9645\u5316\u7684\u4e8b\u4f8b

2.编辑Spring配置文件,在原有基础上添加国际化资源文件和本地化信息

<!-- 获取数据 -->
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<!-- 表示多语言配置文件在根路径下,以language开头的文件 -->
		<property name="basename" value="classpath:language" />
		<property name="useCodeAsDefaultMessage" value="true" />
	</bean>
	
	<!-- 获取本地化信息 -->  
	<mvc:interceptors>
		<bean id="localeChangeInterceptor"
			class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
			<property name="paramName" value="lang" />
		</bean>
	</mvc:interceptors>
	
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />  

3.测试

(1)新建一个controller,用于跳转到指定的国际化测试页面

@Controller
public class Test1 {
    @RequestMapping("/hello.action")
    public String index() {
    	System.out.println("进入hello.action");
        return "content/hello.jsp";
    }
}

(2)新建hello.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
    <title>SpringMVC<spring:message code="internationalisation"/></title>
</head>
<body>
    Language:
    <a href="?lang=zh_CN"><spring:message code="language.cn"/></a>    
    <a href="?lang=en_US"><spring:message code="language.en"/></a>
    <h1>
        <spring:message code="welcome"/>
    </h1>
    当前语言: ${pageContext.response.locale }
</body>
</html>

访问hello.action地址,跳转到hello.jsp页面


案例参考至:https://blog.csdn.net/u013360850/article/details/70860144/

国际化实现原理

分为三大步

(1)本地化信息获取

(2)数据获取

(3)格式化

下面分别来解释下这三步分别实现的功能。

(1)本地化信息获取

      Spring MVC的DispatcherServlet类会在initLocaleResolver方法中查找一个locale resolver,如果没有找到就会用默认的AcceptHeaderLocaleResolver类。locale resolver会去根据请求Request设置当前的locale信息。除了resolver类,还可以定义拦截器去设置locale信息。

AcceptHeaderLocaleResolver

        解析request的header中的accept-language值,这个值通常包含客户端支持的本地化信息,通过这个值可以获取本地化信息。

CookieLocaleResolver

        通过cookie去存取本地化信息,客户端可以在cookie中存储一个指定名字的值代表本地化信息,然后这个类获取后做相应的解析即可。

SessionLocaleResolver

        通过request获取本地化信息,然后存在HttpSession中,由此可以看出本地化信息存取依赖于session的生命周期。

LocaleChangeInterceptor

      这个拦截器会拦截请求中的参数,然后根据参数去调用LocaleResolver的setLocale()方法,改变当前的locale值。
在案例中,使用的就是这种方式来获取本地化信息,那为什么我们要配置localeResolver这个bean呢?
因为LocaleChangeInterceptor需要调用LocaleResolver的setLocale()方法,这里面用到了CookieLocaleResolver,当然也可以用其他的LocaleResolver实现类。
LocaleChangeInterceptor类中的preHandler()方法
@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) {
					throw new IllegalStateException(
							"No LocaleResolver found: not in a DispatcherServlet request?");
				}
				try {
					localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
				}
				catch (IllegalArgumentException ex) {
					if (isIgnoreInvalidLocale()) {
						logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
					}
					else {
						throw ex;
					}
				}
			}
		}
(2)数据获取
      得到本地化信息后,就可以从相应的properties文件中获取Spring MVC的数据处理定义了一个接口MessageSource,该接口定义了数据获取的方法。方法如下:
■ String getMessage(String code, Object[] args, String defaultMessage, Locale locale)
这里code为属性文件中的key值,args是文件中需要替换的参数值,defaultMessage是找不到内容时的默认内容,locale为本地化信息。
■ String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
这个方法与上面的方法类似,只是没有了默认内容,而是找不到内容时抛出异常。
■ String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
这里参数中有个新接口MessageSourceResolvable,对前面的参数进行了封装,locale为本地化信息。
(3)格式化
         第(2)步已经获取到了数据,有些时候数据获取到之后可以直接展示,但是如果涉及到时间、数字、金额、动态文本等数据时,又需要额外做下处理了,因为本身这些数据就是本地化敏感的,这时就需要对相应的数据进行格式化操作。
数字与金额:使用DataFormate类进行处理;DecimalFormatele类,小数的格式化处理
时间与日期:SimpleDateFormate类和DateTimeFormatter类

文本:MessageFormate类


猜你喜欢

转载自blog.csdn.net/qq_41541619/article/details/80459932