STRUTS 2 国际化并自定义切换语言的问题解决
2013-10-23 18:52
471 查看
在struts2配置文件struts.xml中添加好国际化拦截器,struts。properties中指定好资源文件后(这2步网上一搜一大把,就不再写),项目的国际化就弄好了。现在把浏览器的语言改成其他语言能顺利国际化访问。
这一步做好后,我们开始要做自定义国际化切换的功能。这个功能网上搜到的内容都是错误,所以特此在此记录下,以方便后来人。
网上很多说自定义国际化切换只要修改保存在session中的struts2国际化常量的值“WW_TRANS_I18N_LOCALE”就行了。
实际上时完全错误,我们先看看struts2国际化的步骤:
1、判断struts.locale属性(在struts.properties)是否有值,如果有值,将这个值转换为Locale对象保存到ActionContext中。
2、如果没有设置struts.locale,从浏览器发送的请求报头里获得语言信息,创建Locale对象,保存到ActionContext中。
3、I18nInterceptor拦截器获取名为request_locale请求参数的值,如果这个值存在则创建以这个值的Locale对象,然后将这个对象作为session的属性(WW_TRANS_I18N_LOCALE)保存,并保存到ActionContext中。
在修改session的WW_TRANS_I18N_LOCALE值和request_locale等无效之后,发现程序始终是只会读取浏览器发送过来的区域信息。估计这是struts2国际化得BUG了。
知道了struts2的原理后,就好解决,我们现在要做的就是用用户自定义切换的国际化区域信息来替代浏览器请求报头里的语言信息。
先写一个过滤器,代码如下:
Java代码
public class I18nFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest r = (HttpServletRequest) req;
MyRequestWrapper request = new MyRequestWrapper(r);
filterChain.doFilter(request, resp);
}
}
配置为拦截所有请求
Java代码
<filter>
<filter-name>i18nFilter</filter-name>
<filter-class>com.xxx.common.filter.I18nFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>i18nFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
这个拦截器的关键就是使用httpRequestWrapper,保装request。
这个包装器代码如下:
Java代码
public class MyRequestWrapper extends HttpServletRequestWrapper {
private Locale locale = null;
public MyRequestWrapper(HttpServletRequest request) {
super(request);
HttpSession session = request.getSession();
locale = (Locale) session.getAttribute("WW_TRANS_I18N_LOCALE");
}
/**
* struts2的BUG,如果重定向的话,国际化默认取HTTP请求头中的参数 替换HTTP请求参数
**/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if ("Accept-Language".equals(name) && locale != null) {
value = locale.getLanguage() + "_" + locale.getCountry()
+ value.substring(6, value.length());
}
return value;
}
@Override
public Locale getLocale() {
if (locale != null) {
return locale;
}
return super.getLocale();
}
}
这个request包装器主要作用就是从session里获得区域对象,并修改请求报头,从而实现了自定义国际化切换。
如果本方法有问题或者各位有更好的方法,请告知。谢谢
这一步做好后,我们开始要做自定义国际化切换的功能。这个功能网上搜到的内容都是错误,所以特此在此记录下,以方便后来人。
网上很多说自定义国际化切换只要修改保存在session中的struts2国际化常量的值“WW_TRANS_I18N_LOCALE”就行了。
实际上时完全错误,我们先看看struts2国际化的步骤:
1、判断struts.locale属性(在struts.properties)是否有值,如果有值,将这个值转换为Locale对象保存到ActionContext中。
2、如果没有设置struts.locale,从浏览器发送的请求报头里获得语言信息,创建Locale对象,保存到ActionContext中。
3、I18nInterceptor拦截器获取名为request_locale请求参数的值,如果这个值存在则创建以这个值的Locale对象,然后将这个对象作为session的属性(WW_TRANS_I18N_LOCALE)保存,并保存到ActionContext中。
在修改session的WW_TRANS_I18N_LOCALE值和request_locale等无效之后,发现程序始终是只会读取浏览器发送过来的区域信息。估计这是struts2国际化得BUG了。
知道了struts2的原理后,就好解决,我们现在要做的就是用用户自定义切换的国际化区域信息来替代浏览器请求报头里的语言信息。
先写一个过滤器,代码如下:
Java代码
public class I18nFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest r = (HttpServletRequest) req;
MyRequestWrapper request = new MyRequestWrapper(r);
filterChain.doFilter(request, resp);
}
}
配置为拦截所有请求
Java代码
<filter>
<filter-name>i18nFilter</filter-name>
<filter-class>com.xxx.common.filter.I18nFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>i18nFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
这个拦截器的关键就是使用httpRequestWrapper,保装request。
这个包装器代码如下:
Java代码
public class MyRequestWrapper extends HttpServletRequestWrapper {
private Locale locale = null;
public MyRequestWrapper(HttpServletRequest request) {
super(request);
HttpSession session = request.getSession();
locale = (Locale) session.getAttribute("WW_TRANS_I18N_LOCALE");
}
/**
* struts2的BUG,如果重定向的话,国际化默认取HTTP请求头中的参数 替换HTTP请求参数
**/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if ("Accept-Language".equals(name) && locale != null) {
value = locale.getLanguage() + "_" + locale.getCountry()
+ value.substring(6, value.length());
}
return value;
}
@Override
public Locale getLocale() {
if (locale != null) {
return locale;
}
return super.getLocale();
}
}
这个request包装器主要作用就是从session里获得区域对象,并修改请求报头,从而实现了自定义国际化切换。
如果本方法有问题或者各位有更好的方法,请告知。谢谢
相关文章推荐
- struts多国语言国际化处理(现以中文英文切换为例)
- Android国际化问题以及在应用内切换不同语言设置
- 解决struts国际化和中文问题
- 通过 Method swizzing解决项目模块化后语言国际化的问题
- 语言切换,横竖屏切换,物理键盘推出导致activity重启原因分析和问题解决
- DWZ (JUI) 教程 国际化问题(多语言/语言切换)
- Struts国际化问题解决
- struts国际化问题解决方案
- struts国际化问题解决方案
- struts多国语言国际化处理(现以中文英文切换为例)
- 解决 Struts 国际化资源的中文编码问题
- struts--动态访问国际化资源(国家/语言切换)
- Struts国际化问题解决
- 自定义照相机实现前后切换摄像头以及拍照预览各种问题解决
- 解决Android 7.0 App内切换语言不生效的问题
- 解决android 语言国际化在横竖屏切换后,设置的语言又变为本地语言
- struts解决中文乱码和国际化问题
- 终极Struts中文及其它语言文字处理问题(文字国际化)
- 不同database排序方式,不同语言,如何解决国际化编程问题
- 解决struts国际化和中文问题