Struts2国际化用法及源码解析

1. 国际化的目标
1). 如何配置国际化资源文件
I.   Action 范围资源文件: 在Action类文件所在的路径建立名为 ActionName_language_country.properties 的文件
II.  包范围资源文件: 在包的根路径下建立文件名为 package_language_country.properties 的属性文件,
一旦建立,处于该包下的所有 Action 都可以访问该资源文件。注意:包范围资源文件的 baseName 就是package,不是Action所在的包名。
III. 全局资源文件
    > 命名方式: basename_language_country.properties
    > struts.xml <constant name="struts.custom.i18n.resources" value="baseName"/>
IV.  国际化资源文件加载的顺序如何呢 ? 离当前 Action 较近的将被优先加载.
假设我们在某个 ChildAction 中调用了getText("username"):
(1) 加载和 ChildAction 的类文件在同一个包下的系列资源文件 ChildAction.properties
(2) 加载  ChildAction 实现的接口 IChild,且和 IChildn 在同一个包下 IChild.properties 系列资源文件。
(3) 加载 ChildAction 父类 Parent,且和 Parent 在同一个包下的 baseName 为 Parent.properties 系列资源文件。
(4) 若 ChildAction 实现 ModelDriven 接口,则对于getModel()方法返回的model 对象,重新执行第(1)步操作。
(5) 查找当前包下 package.properties 系列资源文件。
(6) 沿着当前包上溯,直到最顶层包来查找 package.properties 的系列资源文件。
(7) 查找 struts.custom.i18n.resources 常量指定 baseName 的系列资源文件。
(8) 直接输出该key的字符串值。
2). 如何在页面上 和 Action 类中访问国际化资源文件的  value 值

I. 在 Action 类中. 若 Action 实现了 TextProvider 接口, 则可以调用其 getText() 方法获取 value 值
    > 通过继承 ActionSupport 的方式。

II. 页面上可以使用 s:text 标签; 对于表单标签可以使用表单标签的 key 属性值
    > 若有占位符, 则可以使用 s:text 标签的 s:param 子标签来填充占位符
    > 可以利用标签和 OGNL 表达式直接访问值栈中的属性值(对象栈 和 Map 栈)
    time=Time:{0}
    <s:text name="time">
        <s:param value="date"></s:param>
    </s:text>
    ------------------------------------
    time2=Time:${date}
    <s:text name="time2"></s:text>


3). 实现通过超链接切换语言.

I.  关键之处在于知道 Struts2 框架是如何确定 Local 对象的 !
II. 可以通过阅读 I18N 拦截器知道.
III. 具体确定 Locale 对象的过程:

    > Struts2 使用 i18n 拦截器 处理国际化,并且将其注册在默认的拦截器栈中
    > i18n拦截器在执行Action方法前,自动查找请求中一个名为 request_locale 的参数。
          如果该参数存在,拦截器就将其作为参数,转换成Locale对象,并将其设为用户默认的Locale(代表国家/语言环境)。
          并把其设置为 session 的 WW_TRANS_I18N_LOCALE 属性
    > 若 request 没有名为request_locale 的参数,则 i18n 拦截器会从 Session 中获取 WW_TRANS_I18N_LOCALE 的属性值,
         若该值不为空,则将该属性值设置为浏览者的默认Locale
    > 若 session 中的 WW_TRANS_I18N_LOCALE 的属性值为空,则从 ActionContext 中获取 Locale 对象。

IV.  具体实现: 只需要在超连接的后面附着  request_locale 的请求参数, 值是 语言国家 代码.
    <a href="testI18n.action?request_locale=en_US">English</a>
    <a href="testI18n.action?request_locale=zh_CN">中文</a>

    > 注意: 超链接必须是一个 Struts2 的请求, 即使 i18n 拦截器工作!

   
使用label标签时要用%{getText{'username'}}方式也可以从国际化资源文件中获取value值  因为此时在对象栈中有
DefaultTypeProvider的一个实例 该对象中提供访问资源化文件的方法 同时还要通知label中放入的不再是普通的字符串
而是一个OGNL表达式  可以使用%{}包装起来

如果form的主题为simple的时候  所有设置都不起作用  
这时使用s:text 标签 和强制ognl解析

有占位符的国际化资源文件的输出方式:
     新建acton I18nAction

还可以使用time=Time:${date} 来直接获取值栈中的属性值

实现通过超链接切换语言:
     关键之处在于struts2框架是如何确定Local对象的 i18n拦截器  I18nInterceptor 

publicStringintercept(ActionInvocationinvocation)throwsException{
        if ( LOG . isDebugEnabled ()) {
            LOG . debug ( "intercept '#0/#1' {" ,
                invocation . getProxy (). getNamespace (), invocation . getProxy (). getActionName ());
        }
        //get requested locale
        Map < String , Object > params = invocation . getInvocationContext (). getParameters ();
                          //保持session的falg默认为true
        boolean storeInSession = true ;
          //parameteName 为request_locale
          //requsetedLocale为转换过的浏览器参数
        Object requestedLocale = findLocaleParameter ( params , parameterName );
<!--
     --- findLocaleParameter
  private Object findLocaleParameter ( Map < String , Object > params , String parameterName ) {
          //将从浏览器带过来的request_locale参数保存到requestedLoclae中
        Object requestedLocale = params . remove ( parameterName );
          //如果requestedLocale不为空 类型是数组  并取长度是1
        if ( requestedLocale != null && requestedLocale . getClass (). isArray ()
                && (( Object []) requestedLocale ). length == 1 ) {
               //将数组中的参数取出赋给requestedLocale
            requestedLocale = (( Object []) requestedLocale )[ 0 ];

            if ( LOG . isDebugEnabled ()) {
                LOG . debug ( "requested_locale=#0" , requestedLocale );
            }
        }
        return requestedLocale ;
    }
-->         //如果请求擦拭你为空就从requestOnlyParmeteName中去找
        if ( requestedLocale == null ) {
               //requestOnlyParameterName默认为request_only_locale
            requestedLocale = findLocaleParameter ( params , requestOnlyParameterName );
               //如果上面的保存到request中的不为空 则将保存到session的flag设置为false
            if ( requestedLocale != null ) {
                storeInSession = false ;
            }
        }
          //将找到的requestLocale参数赋值给local
        Locale locale = getLocaleFromParam ( requestedLocale );
<!--      
     --- getLocaleFromParam
     protected Locale getLocaleFromParam ( Object requestedLocale ) {
        Locale locale = null ;
                         //如果传进来的参数不为空
        if ( requestedLocale != null ) {
               //如果参数的类型为Locale 就强转为Locale  如果不是就执行下面的代码 将将参数转换为Locale类型并赋值
            locale = ( requestedLocale instanceof Locale ) ?
                    ( Locale ) requestedLocale :
                    LocalizedTextUtil . localeFromString ( requestedLocale . toString (), null );
            if ( locale != null && LOG . isDebugEnabled ()) {
                LOG . debug ( "applied request locale=#0" , locale );
            }
        }
        return locale ;
    }
-->
       //获取sessionMap
        Map < String , Object > session = invocation . getInvocationContext (). getSession ();
          //如果session不为空  并取locale不为空  就把参数保存到session中
        if ( session != null ) {
            synchronized ( session ) {
                if ( locale == null ) {
                    storeInSession = false ;
                    locale = readStoredLocale ( invocation , session );
                }

                if ( storeInSession ) {
                    session . put ( attributeName , locale );
                }
            }
        }
          
        saveLocale ( invocation , locale );
<!--
     //将获取到的locale值放入context 中   在值栈的栈顶可见
     protected void saveLocale ( ActionInvocation invocation , Locale locale ) {
        invocation . getInvocationContext (). setLocale ( locale );
    }
-->

        if ( LOG . isDebugEnabled ()) {
            LOG . debug ( "before Locale=#0" , invocation . getStack (). findValue ( "locale" ));
        }
        final String result = invocation . invoke ();
        if ( LOG . isDebugEnabled ()) {
            LOG . debug ( "after Locale=#0" , invocation . getStack (). findValue ( "locale" ));
            LOG . debug ( "intercept } " );
        }
        return result ;
    }

//默认请况下走的是左边这条线  如果通过url改变locle的值则走右边  设置之后 如果没有设置的url访问就会从session取对应的locale参数去使用



以上个人见解 若有不正之处 欢迎讨论修改

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值