1. 需求:
通过请求头中指定的属性例如lang指定本次请求需要响应数据的语言
2. 解决方案
1. 创建国际化资源
1. 使用idea创建资源组
2. 将不同语言的数据写入对应的文件,保证key相同
messages_en_US.properties
000000=operation success
messages_zh_CN.properties
000000=操作成功
2. 编写配置
1. application.yml
增加国际化目录配置
spring:
messages:
#指定国际化资源文件资源组
basename: i18n/messages
2. 增加配置类 从请求头获取多语言关键字
package com.fkp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
@Configuration
public class I18nConfiguration {
@Bean
public LocaleResolver localeResolver(){
return new I18nLocaleResolver();
}
static class I18nLocaleResolver implements LocaleResolver{
@Override
public Locale resolveLocale(HttpServletRequest request) {
String lang = request.getHeader("lang");
Locale locale = Locale.getDefault();
if("zh_CN".equals(lang)){
locale = Locale.SIMPLIFIED_CHINESE;
}else if("en_US".equals(lang)){
locale = Locale.US;
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
}
3. 使用国际化
1. 定义国际化工具类 I18nUtils
package com.fkp.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
@Component
public class I18nUtils {
@Autowired
private MessageSource messageSource;
public String getMessage(String key){
String langMessage = key;
try {
langMessage = messageSource.getMessage(key, new Object[]{}, LocaleContextHolder.getLocale());
}catch (NoSuchMessageException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
langMessage = "i18n inner error!";
}
return langMessage;
}
}
2. 定义统一的返回对象 RestResponse
package com.fkp.param;
import com.fkp.util.I18nUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@Component
public class RestResponse<T> implements Serializable {
private static final long serialVersionUID = 2621638727631497840L;
private String code;
private String status;
private String msg;
private T data;
private static final String CODE_SUCCESS = "000000";
private static final String STATUS_SUCCESS = "success";
private static final String STATUS_FAIL = "fail";
private static I18nUtils i18nUtils;
@Autowired
private void setI18nUtils(I18nUtils i18nUtils){
RestResponse.i18nUtils = i18nUtils;
}
public RestResponse() {
}
public RestResponse(String code, String status, String msg) {
this.code = code;
this.status = status;
this.msg = i18nUtils.getMessage(msg);
}
public RestResponse(String code, String status, String msg, T data) {
this.code = code;
this.status = status;
this.msg = i18nUtils.getMessage(msg);
this.data = data;
}
public static <T> RestResponse<T> success(){
RestResponse<T> res = new RestResponse<>();
res.setCode(CODE_SUCCESS);
res.setStatus(STATUS_SUCCESS);
res.setMsg(i18nUtils.getMessage(CODE_SUCCESS));
return res;
}
public static <T> RestResponse<T> success(String msg){
RestResponse<T> res = new RestResponse<>();
res.setCode(CODE_SUCCESS);
res.setStatus(STATUS_SUCCESS);
res.setMsg(i18nUtils.getMessage(msg));
return res;
}
public static <T> RestResponse<T> success(T data){
RestResponse<T> res = new RestResponse<>();
res.setCode(CODE_SUCCESS);
res.setStatus(STATUS_SUCCESS);
res.setMsg(i18nUtils.getMessage(CODE_SUCCESS));
res.setData(data);
return res;
}
public static <T> RestResponse<T> success(String msg, T data){
RestResponse<T> res = new RestResponse<>();
res.setCode(CODE_SUCCESS);
res.setStatus(STATUS_SUCCESS);
res.setMsg(i18nUtils.getMessage(msg));
res.setData(data);
return res;
}
public static <T> RestResponse<T> fail(String code){
RestResponse<T> res = new RestResponse<>();
res.setCode(code);
res.setStatus(STATUS_FAIL);
res.setMsg(i18nUtils.getMessage(code));
return res;
}
public static <T> RestResponse<T> fail(String code, String msg){
RestResponse<T> res = new RestResponse<>();
res.setCode(code);
res.setStatus(STATUS_FAIL);
res.setMsg(i18nUtils.getMessage(msg));
return res;
}
public static <T> RestResponse<T> fail(String code, T data){
RestResponse<T> res = new RestResponse<>();
res.setCode(code);
res.setStatus(STATUS_FAIL);
res.setMsg(i18nUtils.getMessage(code));
res.setData(data);
return res;
}
public static <T> RestResponse<T> fail(String code, String msg, T data){
RestResponse<T> res = new RestResponse<>();
res.setCode(code);
res.setStatus(STATUS_FAIL);
res.setMsg(i18nUtils.getMessage(msg));
res.setData(data);
return res;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
3. 定义Controller用来测试
package com.fkp.controller;
import com.fkp.param.RestResponse;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/i18n")
public class I18nController {
@RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public RestResponse<User> test(@RequestParam("name") String name){
User user = new User();
user.setName(name);
return RestResponse.success(user);
}
static class User{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
4. 测试
1. 请求头lang为en_US
2. 请求头lang为zh_CN
3.备注
1.当new对象时,该对象中普通注入的对象无法注入,需要使用静态注入,静态注入方式可使用set方法注入,若对象中的属性想要普通注入则该对象必须要以注入的方式创建,不可new.
在定义RestResponse时需要使用I18nUtils,为了保证其既可以使用new对象的方式使用也可以使用静态方法的方式使用,因此i18n对象需要静态注入,前提保证RestResponse对象使用@Component注解标注即让Spring容器管理。
private static I18nUtils i18nUtils;
@Autowired
private void setI18nUtils(I18nUtils i18nUtils){
RestResponse.i18nUtils = i18nUtils;
}
4. 改进
1. 通过在I18nUtils类中直接注入静态的MessageSource对象,将getMessage方法定义为静态方法,则在RestResponse类中不需要注入静态的I8nUtils对象直接调用其静态方法即可,则RestResponse类也无需交由Spring容器管理。