spring 項目國際化,前後端分離
一般一個項目稍微有可能的話國際化是基本需求,提前做好。
國際化嘛,首先是時間,其次就是語言了。我這邊就不談時間了,主要針對語言。
注:防止亂碼國際化(數據庫和服務器)肯定統一UTF-8編碼。
項目後端提示國際化
1. LocalResolwer
利用spring對國際化的支持,使用內置的語言處理器。
重寫LocalResolwer,這個類其實已經得到了官方實現,但是我的項目是基於jwt的,所以決定自定義比較適合。
然後將自定義的處理器添加到WebMVCConfig中。
注意:通過獲取瀏覽器請求中自帶的header中的Accept-Language參數,也可以通過前後端約定自己設置的來。
2.國際化資源配置
IDEA環境下,在resources下新建Resource Bound文件,加上英文key和value。
在yml配置文件中,加上以下配置,注意空格對齊問題。
spring
#國際化
messages:
basename: i18n/message
encoding: UTF-8
# 失效時間,-1永不
cache-duration: -1
2.MessageSource
通過上面的配置,我們就可以拿到MessageSource,在代碼中可以通過@Autowired來注入使用。
3.統一定義返回類
像我的項目,所以的返回和異常都是從Result 繼承下去的,所以會形成一個很好的規範,同時在所有返回中只能存在資源文件中的key,在後面做替換。有助於下一步驟。
4.自定義過濾器
通過自定義過濾器I18NFilter,該類基礎自javax.servlet.Filter;
在I18NFilter中,對所以的返回進行過濾,將所有的key替換爲對應語言的國際化資源。
項目中的枚舉類型或者常量國際化
1、對枚舉類型的GET方法進行改造。
2、資源文件中將枚舉值進行配置。
public enum EnumSuccessOrError {
SUCCESS(0, “SUCCESS”),
ERROR(1, “ERROR”);
/**
* 返回狀態碼
*/
private int statusCode;
/**
* 返回狀態信息
*/
private String statusMsg;
EnumSuccessOrError(int statusCode, String statusMsg) {
this.statusCode = statusCode;
this.statusMsg = statusMsg;
}
private MessageSource messageSource;
public EnumSuccessOrError setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
return this;
}
//通過靜態內部類的方式注入bean,並賦值到枚舉中
@Component
public static class ReportTypeServiceInjector {
@Autowired
private MessageSource messageSource;
@PostConstruct
public void postConstruct() {
for (EnumSuccessOrError rt : EnumSet.allOf(EnumSuccessOrError.class))
rt.setMessageSource(messageSource);
}
}
/**
* @return the statusCode
*/
public int getStatusCode() {
return statusCode;
}
/**
* @return the statusMsg,根據語言環境返回國際化字符串
*/
public String getStatusMsg() {
return messageSource.getMessage(statusMsg,null,statusMsg, LocaleContextHolder.getLocale());
}
數據庫部分
對於數據庫比如字典表這類表,只能做特殊處理,增加language字段,通過請求中的header語言進行特殊查詢。
也有看到用資源表,進行整個翻譯的這種說法,但是感覺明顯就很奇怪,比較這種表的情況屬於特例,其他的表一般不會存在這個問題,都是用戶自己存自己看。
還有那種實在是需要多個語言,而且業務需要的,比如存文章,就是非要多個語言,這種有看到多表或者多庫做處理的,具體也沒了解。基本上這種肯定就分佈式,不通地區訪問不同地區的服務器,NGINX就處理了,反而不需要這麼麻煩了。
代碼地址:github,過兩天放上去
/**
*國際化工具類
*@author Angel–守護天使
*@version v.0.1
*@date 2016年8月5日下午2:44:03
*/
@Component
publicclassLocaleMessageSourceService {
@Resource
private MessageSourcemessageSource;
/**
*@param code:對應messages配置的key.
*@return
*/
public StringgetMessage(Stringcode){
returnthis.getMessage(code,new Object[]{});
}
public StringgetMessage(Stringcode,StringdefaultMessage){
returnthis.getMessage(code,null,defaultMessage);
}
public StringgetMessage(Stringcode,StringdefaultMessage,Localelocale){
returnthis.getMessage(code,null,defaultMessage,locale);
}
public StringgetMessage(Stringcode,Localelocale){
returnthis.getMessage(code,null,"",locale);
}
/**
*
*@param code:對應messages配置的key.
*@param args :數組參數.
*@return
*/
public StringgetMessage(Stringcode,Object[]args){
returnthis.getMessage(code,args,"");
}
public StringgetMessage(Stringcode,Object[]args,Localelocale){
returnthis.getMessage(code,args,"",locale);
}
/**
*
*@param code:對應messages配置的key.
*@param args :數組參數.
*@param defaultMessage :沒有設置key的時候的默認值.
*@return
*/
public StringgetMessage(Stringcode,Object[]args,StringdefaultMessage){
//這裏使用比較方便的方法,不依賴request.
Locale locale =LocaleContextHolder.getLocale();
returnthis.getMessage(code,args,defaultMessage,locale);
}
/**
*指定語言.
*@param code
*@param args
*@param defaultMessage
*@param locale
*@return
*/
public StringgetMessage(Stringcode,Object[]args,StringdefaultMessage,Localelocale){
returnmessageSource.getMessage(code,args,defaultMessage,locale);
}