基于請求URL的國際化實現(xiàn)方式
原理:使用spring的request bean保存相應(yīng)的國際化組件,這樣保證同一個請求的國際化相同继阻,也是在微服務(wù)處理國際化的一種方式示括。需要針對每個請求做不同的國際化
實現(xiàn)所以需要姆怪,相應(yīng)的攔截器去處理對應(yīng)請求域中的國際化組件
- 配置文件:
- spring容器配置applicationContext.xml溯乒,中添加取得信息的messageSource,放在spring容器而非springmvc容器加載是因為代碼中有Service的注解依賴于他
<!-- 國際換的service依賴于他匪煌,所以從mvc提到前面 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<!-- 國際化信息所在的文件名 -->
<property name="basename" value="messages/messages" />
<property name="defaultEncoding" value="UTF-8"/>
<!-- 如果在國際化資源文件中找不到對應(yīng)代碼的信息责蝠,就用這個代碼作為名稱 -->
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
- springmvc容器配置攔截器,注意攔截器的順序萎庭,國際化的攔截器在處理請求的攔截器前面
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 國際化操作攔截器 如果采用基于(請求/Session/Cookie)則必需配置 -->
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="locale"/>
</bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 需攔截的地址 -->
<!-- 級目錄 -->
<mvc:mapping path="/*" />
<mvc:mapping path="/*/*" />
<!-- 需排除攔截的地址 -->
<mvc:exclude-mapping path="/*.html"/>
<bean class="cn.xx.xx.xx.interceptor.ControllerInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
<!-- 基于url的國際化 id必須為localeResolver否則國際化組件無法識別霜医,UrlAcceptHeaderLocaleResolver為自定義實現(xiàn)部分-->
<bean id="localeResolver" class="cn.abcsys.devops.application.service.UrlAcceptHeaderLocaleResolver"/>
- UrlAcceptHeaderLocaleResolver作為localeResolver國際urlLocal
/**
* Copyright: Copyright (c) 2018 LanRu-Caifu
* @author xzg
* 2018年2月6日
* @ClassName: UrlAcceptHeaderLocaleResolver.java
* @Description: 國際化攔截請求后對請求更改Local
* @version: v1.0.0
*/
public class UrlAcceptHeaderLocaleResolver extends AcceptHeaderLocaleResolver {
private Locale urlLocal;
public Locale resolveLocale(HttpServletRequest request) {
return urlLocal != null?urlLocal:request.getLocale();
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
urlLocal = locale;
}
}
- spring中的request bean依賴于接口實現(xiàn),下面是其接口和對應(yīng)的實現(xiàn)類
public interface I18nSessionService {
public void setRc(RequestContext rc);
public void setRcByRequest(HttpServletRequest request);
public String getMessage(String key);
public String getMessage(String key,Object info);
public String getMessage(String key,Object...objects);
}
- 下面注解主要為設(shè)置作用域為request擎椰,注入messageSource組件支子,并提供RequestContext用于切換語言配置國際化
@Component
@RequestScope(proxyMode = ScopedProxyMode.INTERFACES)
public class I18nSessionServiceImpl implements I18nSessionService {
@Autowired
@Qualifier("messageSource")
private MessageSource resources;
//前端設(shè)置切換語言是設(shè)置
private RequestContext rc ;
public RequestContext getRc() {
return rc;
}
@Override
public void setRcByRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.rc = new RequestContext(request);
}
@Override
public void setRc(RequestContext rc) {
this.rc = rc;
}
@Override
public String getMessage(String key) {
// TODO Auto-generated method stub
if(null != getRc()){
return getRc().getMessage(key);
}
return resources.getMessage(key, null, null);
}
@Override
public String getMessage(String key, Object info) {
// TODO Auto-generated method stub
if(null != getRc()){
return getRc().getMessage(key, new Object[]{info});
}
return resources.getMessage(key, new Object[]{info}, null);
}
@Override
public String getMessage(String key, Object... objects) {
if(null != getRc()){
return getRc().getMessage(key, objects);
}
return resources.getMessage(key, objects, null);
}
}
- 自定義的攔截器中處理创肥,國際化組件的請求bean
@Component
public class ControllerInterceptor implements HandlerInterceptor {
/**
* 在Controller方法前進(jìn)行攔截
*/
@Resource
private I18nSessionService i18nSessionService;
private static Logger log = Logger.getLogger("ControllerInterceptor");
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
log.info("RequestURI :"+request.getRequestURI());
//解決跨域
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods","POST");
response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type");
//攔截器中對所有的請求處理达舒,保存到request bean中
i18nSessionService.setRcByRequest(request);
return true;
}
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* 在Controller方法后進(jìn)行攔截
*/
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
- 使用方式
//發(fā)送請求 http://localhost:8080/testI18n.do?locale=en_US 或者h(yuǎn)ttp://localhost:8080/testI18n.do?locale=zh_CN
@Resource
private I18nSessionService is;
@RequestMapping(value = "/testI18n.do", method = { RequestMethod.POST,RequestMethod.GET})
public @ResponseBody
Result testI18n(){
return new Result(true, is.getMessage("argument.required"), "");
}
- 總結(jié):以上就是基本實現(xiàn)過程。在微服務(wù)中由于服務(wù)發(fā)現(xiàn)提供的服務(wù)模塊會自適應(yīng)調(diào)整所以不適合使用session 的方式處理國際化叹侄。這里使用request和url將粒度劃分的更細(xì)巩搏,處理也更靈活