1. 程式人生 > >SpringMVC之國際化

SpringMVC之國際化

SpringMVC的國際化的具體實現方式有:1.瀏覽器語言環境;2..session;3.cookies;4.URL;

1.瀏覽器語言切換語言

springmvc配置檔案

<!-- 國際化資原始檔 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="fileEncodings" value="utf-8"/>
  <property name="cacheSeconds" value="120"/>
  <property name="useCodeAsDefaultMessage" value="false" />
  <!-- <property name="basename" value="/WEB-INF/i18n/sys/message" /> -->
  <property name="basenames">
    <list>
	  <value>/WEB-INF/i18n/sys/message</value>
	  <value>/WEB-INF/i18n/common/message</value>
    </list>
  </property>
</bean>

basename和basenames的區別為配置檔案分單個檔案和多個檔案,basenames讀取的檔案分別為/WEB-INF/i18n/sys和/WEB-INF/i18n/common目錄下的message字首檔案;簡體中文為message_zh_CN.properties何message_en_US.properties支援更多的語言則根據不同語言代號新增相應檔案,語言代號參考:https://blog.csdn.net/qq_35544379/article/details/78204811

有了上面配置切換瀏覽器語言即可(親測Chrome、Firefox和IE均支援)

在頁面新增spring標籤,如下引用即可


效果如下:


如果切換語言發現無法改變語言,試著清掉快取。

2.Locale放在session

springmvc配置檔案的國際化資原始檔messageSource仍要配置,session方式要加如下配置

<mvc:interceptors>
  <!-- 國際化操作攔截器如果採用基於(請求/Session/Cookie)則必需配置 --> 
  <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>

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

設定session的Locale,這裡方便測試則通過請求引數設定Locale

@RequestMapping("/home")
public String index(HttpServletRequest request, @RequestParam(value="langType", defaultValue="zh") String langType) {
	Locale locale = null;
	if(langType.equals("zh")){
		locale = new Locale("zh", "CN"); 
	}else if(langType.equals("en")){
		locale = new Locale("en", "US"); 
	}else{
		locale = LocaleContextHolder.getLocale();
	}
	request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
	
	return "home";
}
登陸頁面為英文

首頁按引數設定為預設的zh_CN語言


切換語言en_US


不論session設定為何種語言,退出系統,清空session,仍然顯示為瀏覽器語言設定的en_US

3.Locale放在cookie

session和cookie的區別是session的localeResolver為SessionLocaleResolver,cookie的為CookieLocaleResolver;

<mvc:interceptors>
  <!-- 國際化操作攔截器如果採用基於(請求/Session/Cookie)則必需配置 --> 
  <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>

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

cookie設定

@RequestMapping("/home")
public String index(HttpServletRequest request, HttpServletResponse response) {		
	(new CookieLocaleResolver()).setLocale (request, response, new Locale("zh", "CN"));		
	return "home";
}

瀏覽器語言仍是en_US


進入首頁,cookie設定Locale為zh_CN


退出登入仍會顯示為zh_CN


清空cookie方可切換為瀏覽器語言對應的Locale;(tip:瀏覽器清楚內容的快捷鍵Ctrl+Shift+Delete);

4.URL傳遞Locale引數

springmvc配置檔案,參考session和cookie方式,將localeResolver換成本地自定義的com.chensan.common.interceptor.MyAcceptHeaderLocaleResolver;MyAcceptHeaderLocaleResolver檔案內容如下:

package com.chensan.common.interceptor;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;

public class MyAcceptHeaderLocaleResolver extends AcceptHeaderLocaleResolver {
	private Locale myLocal;
	
    public Locale resolveLocale(HttpServletRequest request) {
        return myLocal;
    } 
    
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        myLocal = locale;
    }
}

Controller不再設定Locale

@RequestMapping("/home")
public String index() {		
	return "home";
}

在每次URL訪問時新增引數locale=en_US或locale=zh_CN切換語言





注意:在session方式那裡自定義的langType引數只是給SessionLocaleResolver賦值(只是為了方便測試,不要誤解),並不是URL方式直接設定Locale的值。

無意中發現的,在使用SessionLocaleResolver時在url新增locale=zh_CN或者locale=en_US則可切換語言。剛開始感覺奇怪,但細想想這跟URL方式是一樣大的,只是在URL方式的時候自定義的MyAcceptHeaderLocaleResolver繼承自AcceptHeaderLocaleResolver,也就不感到奇怪了。即只須配置localeResolver,不論SessionLocaleResolver、CookieLocaleResolver還是自定義的localeResolver,就可以用URL加引數locale=zh_CN或者locale=en_US的方式切換語言。

=============================下面內容為後臺驗證的內容,後續會單獨寫一篇

springMVC配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:p="http://www.springframework.org/schema/p" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:mvc="http://www.springframework.org/schema/mvc" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
  
  <!-- 開啟springmvc註解 -->
  <mvc:annotation-driven validator="validator" conversion-service="conversion-service"/>
  
  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass"  value="org.hibernate.validator.HibernateValidator"/>
    <!--不設定則預設為classpath下的 validationMessages_zh_CN.properties -->
    <property name="validationMessageSource" ref="messageSource"/>
  </bean>
  <bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
  <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="fileEncodings" value="utf-8"/>
    <property name="cacheSeconds" value="120"/>
    <property name="useCodeAsDefaultMessage" value="false" />
<!-- 配置單個國際化檔案 -->
<!-- 
<property name="basename" value="/WEB-INF/static/i18n/validateMessages"/>
 -->
<!-- 配置多個國際化檔案 -->
<property name="basenames">
      <list>
        <value>/WEB-INF/i18n/sys/sys</value>
      </list>
    </property>
  </bean>
  
  <!-- 自動掃描包 -->
  <context:component-scan base-package="com.chensan"/>
  
  <!-- springmvc不過濾的目錄和檔案 -->
  <mvc:resources mapping="/public/**" location="/WEB-INF/public/" />
  
  <!-- 配置檢視解析器:如何把Handler方法返回值解析為實際的物理檢視 -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
  </bean>
</beans>
其實在SpringMVCJSR-303規範進行校驗簡單示例已實現了國際化效果,只是本篇需要討論的是如果動態選擇、切換語言版本;

LoginModel(這裡只列出兩個@valid的屬性)

/**
 * 使用者名稱.
 */
@Length(min = 4, max = 50, message="{loginForm.userName.length}")
private String userName;

/**
 * 密碼.
 */
@Length(min = 6, max = 20, message = "{loginForm.password.length}")
private String password;

Controller裡的註解

@RequestMapping(value="/signIn", method=RequestMethod.POST)
public String signIn(@Valid @ModelAttribute("formModel") LoginModel formModel, BindingResult bindingResult) {
	if (bindingResult.hasErrors()) {
		return Login_View_Name;
	}
	
	UserMedic user = currentUserService.getUser(formModel.getUserName());
	if (user == null) {
		bindingResult.rejectValue("userName", "userName.not.exist");
		return Login_View_Name;
	}
	
	String pwd = MDCipher.MD5HexString(formModel.getPassword());
	if (!user.getLoginPwd().equals(pwd)) {
		bindingResult.rejectValue("password", "password.error");
		return Login_View_Name;
	}
	HttpSession session = request.getSession();
	session.setAttribute("loginname", user.getLoginName());//將使用者存到session
	return String.format("redirect:/%s", "home");
}
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="sm"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" href="public/img/favicon.png">
  <title>登入頁</title>
</head>
<body>
  <sf:form modelAttribute="formModel" 
  	action="${pageContext.request.contextPath}/signIn" method="post" role="form">
	<label for="userName">
	  <sm:message code="loginForm.userName"/>
	</label>
    <input type="text" name="userName" id="userName" 
	  placeholder="<sm:message code="loginForm.userName"/>" autofocus>
    <sf:errors path="userName" cssClass="errorMsg"/>
	
	<label for="password">
	  <sm:message code="loginForm.password"/>
	</label>
    <input type="password" name="password" id="password" 
	  placeholder="<sm:message code="loginForm.password"/>">
    <sf:errors path="password" cssClass="errorMsg"/>
  </sf:form>
</body>
</html>

該jsp省略了樣式提交按鈕等等內容,只保留國際化了的部分內容,方便直觀看到如何進行設定的;

其中spring的form標籤中的modelAttribute屬性值對應的Controller中signIn方法的@modelAttribute,用於表單驗證;

spring的errors標籤用於輸出表單驗證錯誤資訊;

spring的message標籤用於輸出內容;

國際化檔案在WEB-INF/static/i18n資料夾下

validateMessages_en_US.properties

loginForm.userName = userName
loginForm.password = password
loginForm.userName.length = userName length is {min} to {max} char
loginForm.password.length = password length is {min} to {max} char
userName.not.exist = userName is not exists
password.error = password is error
validateMessages_zh_CN.properties
loginForm.userName = 登入名
loginForm.password = 密碼
loginForm.userName.length = 使用者名稱長度在 {min} 至 {max} 個字元之間
loginForm.password.length = 密碼長度為 {min} 到 {max} 位
userName.not.exist = 使用者不存在
password.error = 密碼錯誤

參考:http://www.cnblogs.com/liukemng/p/3750117.html