Struts2国际化用法及源码解析

本文介绍了Struts2框架中的国际化配置方法,包括不同级别的资源文件配置方式、资源文件加载顺序及如何在Action和页面中访问这些资源。此外,还详细讲解了如何通过超链接实现语言切换。
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
       booleanstoreInSession=true;
          //parameteName 为request_locale
          //requsetedLocale为转换过的浏览器参数
       ObjectrequestedLocale=findLocaleParameter(params,parameterName);
<!--
     ---findLocaleParameter
 privateObjectfindLocaleParameter(Map<String,Object>params,StringparameterName){
          //将从浏览器带过来的request_locale参数保存到requestedLoclae中
       ObjectrequestedLocale=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);
           }
       }
       returnrequestedLocale;
   }
-->         //如果请求擦拭你为空就从requestOnlyParmeteName中去找
       if(requestedLocale==null){
               //requestOnlyParameterName默认为request_only_locale
           requestedLocale=findLocaleParameter(params,requestOnlyParameterName);
               //如果上面的保存到request中的不为空 则将保存到session的flag设置为false
           if(requestedLocale!=null){
               storeInSession=false;
           }
       }
          //将找到的requestLocale参数赋值给local
       Localelocale=getLocaleFromParam(requestedLocale);
<!--     
     ---getLocaleFromParam
     protectedLocalegetLocaleFromParam(ObjectrequestedLocale){
       Localelocale=null;
                         //如果传进来的参数不为空
       if(requestedLocale!=null){
               //如果参数的类型为Locale 就强转为Locale  如果不是就执行下面的代码 将将参数转换为Locale类型并赋值
           locale=(requestedLocaleinstanceofLocale)?
                   (Locale)requestedLocale:
                   LocalizedTextUtil.localeFromString(requestedLocale.toString(),null);
           if(locale!=null&&LOG.isDebugEnabled()){
               LOG.debug("applied request locale=#0",locale);
           }
       }
       returnlocale;
   }
-->
      //获取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 中   在值栈的栈顶可见
     protectedvoidsaveLocale(ActionInvocationinvocation,Localelocale){
       invocation.getInvocationContext().setLocale(locale);
   }
-->

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

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



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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值