structs2本地(国际)化

structs2实现语言本地化,默认是通过获取浏览器的语言(服务器获取:request.getLocale())来作为默认值。
jsp页面使用s标签(引入:<%@taglib prefix=“s” uri=“/structs-tags”%>)支持本地化,如<s:text name=“key”/>

备注:request为javax.servlet.http.HttpServletRequest类型

方式1、structs2自带I18nInterceptor过滤器进行语言本地化,通过访问action(携带request_locale参数自行设定语言)跳转到jsp页面,即可实现指定语言本地化。

备注:需要通过action跳转jsp;一次会话中,指定本地化语言只需进行一次即可(会保存在会话中,一般都是登陆时携带参数指定)

方式2、直接访问jsp无法实现指定语言本地化,因为没有经过过滤器,从而拿到的语言是浏览器作为默认语言。处理方式为:在structs.properties中设定structs.locale=指定语言,如zh_CN、en_US、vi_VN。
原理是org.apache.structs2.dispatcher.Dispatcher类的defaultLocale不为空时,采用该值作为本地化语言
补充:
a、如需动态修改,只需更新defaultLocale(Dispatcher.getInstance().setDefaultLocale(“zh_CN”))即可。
b、直接访问jsp(经过org.apache.structs2.dispatcher.ng.filter.StructsPrepareAndExecuteFilter的doFilter方法)时,拿到ActionContext上下文都是重新创建的。

备注:第二种方式本地化语言的生命周期不是会话(session)周期,而是application,如某一浏览器设置某种语言后,其他浏览器而是该语言。

方式3、修改每次请求传输的请求头accept-language(request.getLocale()拿取的就是该字段的值,如“zh-CN,zh;q=0.9,vi;q=0.8,en;q=0.7”)的值,通过过滤器Filter来修改每次请求的请求头。
javax.servlet.http.HttpServletRequest只能获取请求头,而无法修改请求头,因此需要通过反射来修改请求头数据,此处需要引入tomcat-coyote.jar(在tomcat安装目录lib下可以找到):

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @Author xiye
 * @File I18nFilter
 * @Date 2021/5/11 10:12
 * @Desc 动态设置本地化语言,一次会话作为生命周期
 */
public class I18nFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpSession session = httpServletRequest.getSession();
        	// httpServletRequest.getLocale() --> Header(请求头)的accept-language字段
            if (session != null) {
                // request_locale作为参数目的: structs2自带的本地化拦截器为该参数名
                // 该值形如: zh_CN、en_US、vi_VN等
                String request_locale = request.getParameter("request_locale");
                if (request_locale != null) {
                    session.setAttribute("GM_I18N_LOCALE", request_locale);
                }
                // 将本地化语言设置到
                Object ww_trans_i18N_locale = session.getAttribute("GM_I18N_LOCALE");
                if (ww_trans_i18N_locale != null) {
                    reflectSetHeader(httpServletRequest, "accept-language", ((String) ww_trans_i18N_locale).replace("_", "-"));
                }
            }

            chain.doFilter(httpServletRequest, response);
            return;
        } catch (IOException | ServletException ignored) {}
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() { }

    /**
     * @author  xiye
     * @date    2021/5/11  19:17
     * @param	request     HttpServletRequest对象
     * @param	name        请求头字段
     * @param	value       请求头字段值
     * @desc    通过反射修改HttpServletRequest的请求头字段
     * 备注: 需要引入tomcat-coyote.jar包
     * @return  void
     */
    private void reflectSetHeader(HttpServletRequest request, String name, String value){
        Class<? extends HttpServletRequest> requestClass = request.getClass();
        // System.out.println("request实现类="+requestClass.getName()); // org.apache.catalina.connector.RequestFacade,在catalina.jar,但无须引入该包,除非有显示引用该类
        try {
            Field field = requestClass.getDeclaredField("request");
            field.setAccessible(true);
            Object o = field.get(request);
            Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
            coyoteRequest.setAccessible(true);
            Object o1 = coyoteRequest.get(o);
            Field headers = o1.getClass().getDeclaredField("headers");
            headers.setAccessible(true);
            // o3类型: org.apache.tomcat.util.http.MimeHeaders
            Object o3 = headers.get(o1);
            /*// 转换出错
            MimeHeaders o2 = (MimeHeaders) o3;
            o2.addValue(key).setString(value);
            */
            // 先移除,后添加
            o3.getClass().getMethod("removeHeader", String.class).invoke(o3, name);
            // o4类型: org.apache.tomcat.util.buf.MessageBytes
            Object o4 = o3.getClass().getMethod("addValue", String.class).invoke(o3, name);
            Method setString = o4.getClass().getMethod("setString", String.class);
            setString.invoke(o4, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

备注:
1、request.getLocale()应该获取请求头accept-language的第一组值(每一组以逗号分隔。原因不明确,猜测是权重q【0-1之间】越大,优先获取,第一个组值权重应该为1,最大)。
2、该过滤器需要放置在web.xml比较前面(相对其他过滤器配置),放置其他过滤器后面可能导致上面的反射修改失败(实现类不是org.apache.catalina.connector.RequestFacade,不符合以上逻辑而抛异常)

<!-- 2021-05-11 为所有请求头设置本地化语言(从会话获取替换浏览器默认) -->
<filter>
	<filter-name>i18nFilterChain</filter-name>
	<filter-class>xxx.xxx.I18nFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>i18nFilterChain</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

3、过滤器也可以继承org.springframework.web.filter.OncePerRequestFilter

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值