最近在对一个项目进行重构,使用Spring Boot将原来的项目进行功能拆分,使得之后对于功能的装卸能够更加简单快捷。
然后在国际化配置时发现和原来的项目配置有一些出入。
先来讲下Spring Boot中的配置方式吧。
因为原来项目中用的是
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
的
<spring:message code='XXX'/>
标签实现的国际化(并且原项目前台都是jsp页面,所以转成thymeleaf模板成本太大),所以这里主要讲该方式,而Spring boot的thymeleaf模板自身就实现了#{XX}
的国际化实现方式,这个网上也比较容易找到,就不说了。
首先新建一个Spring Boot项目
目录结构
相关配置
pom.xml,相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- jsp支持 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
添加i18n配置文件I18nConfig和MyLocaleResolver
I18nConfig
该文件为设置默认语言,在项目启动时会被spring扫描后初始化。
package com.my.myI18n.config;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class I18nConfig {
private static Logger logger = LoggerFactory.getLogger(I18nConfig.class);
@Bean(name = "localeResolver")
public MyLocaleResolver myLocaleResolver(){
logger.info("#####cookieLocaleResolver---create");
MyLocaleResolver myLocaleResolver = new MyLocaleResolver();
myLocaleResolver.setDefaultLocale(Locale.CHINA);
logger.info("#####cookieLocaleResolver:");
return myLocaleResolver;
}
}
MyLocaleResolver
最核心的设置文件,可以通过setLocale
方法来修改Local值。
实际为一个拦截器,每次加载页面时都会被调用,及每次加载页面时都会设置并修改语言。
package com.my.myI18n.config;
import java.util.Locale;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.support.RequestContextUtils;
public class MyLocaleResolver extends AcceptHeaderLocaleResolver {
private Locale myLocal;
@Override
public Locale resolveLocale(HttpServletRequest request) {
return myLocal==null?request.getLocale():myLocal;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
myLocal = locale;
}
}
application.properties
i18n.messages
意思为在resources/i18n文件夹下,前缀为messages的所有文件
server.port=8080
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
### i18n setting.
spring.messages.basename=i18n.messages
spring.messages.cache-duration=3600
spring.messages.encoding=UTF-8
#spring.messages.fallback-to-system-locale=true
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
新建messages.properties,messages_zh.properties,messages_en.properties几个文件
我这里如果没有messages.properties文件的话运行时会报错,应该是必须要有一个默认文件。
默认文件的作用是当找不到具体的语言文件时,会从默认文件中取值。
所以这里默认文件中的内容和zh中的一样就可以了
内容
zh&默认
commom.layout.header.logout=\u9000\u51FA
en
commom.layout.header.logout=Login Out
其他的jp什么的根据自己项目需要国际化的语言自行添加
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<spring:message code='commom.layout.header.logout'/>
<a href="language?language=zh"> 中文 </a>
<a href="language?language=en"> english </a>
</body>
</html>
然后MyControll.java
package com.my.myI18n.controll;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.support.RequestContextUtils;
@Controller
@RequestMapping(value = "/test")
public class MyControll {
@RequestMapping(value = "/i18nTest")
public String getHome(HttpServletRequest request,HttpServletResponse response) {
return "/index";
}
@RequestMapping(value = "/language")
public String getlanguage(HttpServletRequest request,HttpServletResponse response,String language) {
Locale locale= request.getLocale();
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
language=language.toLowerCase();
if(language==null||language.equals("")){
return "/index";
}else{
if(language.equals("zh")){
localeResolver.setLocale(request, response, Locale.CHINA);
}else if(language.equals("en")){
localeResolver.setLocale(request, response, Locale.ENGLISH);
}else{
localeResolver.setLocale(request, response, Locale.CHINA );
}
}
return "/index";
}
}
现在启动项目尝试下
点击english
OK,成功切换了。
使用cookie持久化
但是在需要重构的项目中,所使用的方式是用一个cookie来持久化用户语言类型,然后使用spring mvc中的一个框架自动设置语言类型的,所以和这里的还有些不同,需要进一步修改。
因为cookie是持久化在客户端的,所以这里可以直接使用js来操作cookie,少了一步与后台的交互,速度也会快很多。这里模拟下项目中的实现方式。
这里使用的cookie名为ClientLanguage
修改index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<spring:message code='commom.layout.header.logout'/>
<!-- <a href="language?language=en"> 中文 </a> -->
<!-- <a href="language?language=zh"> english </a> -->
<a href="javascript:;" onclick="changeLang('zh')"> 中文 </a>
<a href="javascript:;" onclick="changeLang('en')"> english </a>
</body>
<script>
function changeLang(lang){
document.cookie="ClientLanguage="+lang;
location.reload();
}
</script>
</html>
删除MyControll.java中的getlanguage
方法
因为直接在前台就已经将cookie的值设置好了。
然后修改MyLocaleResolver.java文件
使得每次加载时都会从cookie中获取用户语言类型
public Locale resolveLocale(HttpServletRequest request) {
Cookie[] cookies = request.getCookies(); //获取cookie数组
String lang="";
for(Cookie cookie:cookies){//遍历cookie数组
if("ClientLanguage".equals(cookie.getName())) {
lang=cookie.getValue();
break;
}
}
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
// String lang=(String)request.getSession().getAttribute("iLearnLanguage");
if(lang==null||"".equals(lang)) {
myLocal=Locale.CHINA;
}else {
if(lang.equals("zh")) {
myLocal=Locale.CHINA;
}else if(lang.equals("en")) {
myLocal=Locale.ENGLISH;
}else if(lang.equals("ja")) {
myLocal=Locale.JAPAN;
}
}
// return myLocal==null?request.getLocale():myLocal;
return myLocal;
}
然后运行,点击修改为英文,查看cookie
成功切换过来了。
这样是不是更加简单清爽了?实际上只需要添加2个文件(I18nConfig.java,MyLocaleResolver.java),然后在配置文件中添加3行配置,就可以轻松实现国际化。
前台接入也只需如下几行。
<a href="javascript:;" onclick="changeLang('zh')"> 中文 </a>
<a href="javascript:;" onclick="changeLang('en')"> english </a>
</body>
<script>
function changeLang(lang){
document.cookie="ClientLanguage="+lang;
location.reload();
}
</script>