最爱Java

书山有路勤为径,学海无涯苦作舟

2009年10月27日

    Java程序的国际化主要通过三个类完成:

    java.util.ResourceBundle:用于加载一个资源包。

    java.util.Locale:对应一个特定的国家/区域、语言环境。

    java.text.MessageFormat:用于消息格式化。

    而资源文件的命名方式主要有三种:baseName_language_country.properties、baseName_language.properties和baseName.properties。

    以下的程序可以得到Java所支持的语言和国家:

public class LocalList {
    
public static void main(String[] args){
        Locale[] localeList 
= Locale.getAvailableLocales();
        
for (int i=0;i<localeList.length;i++){
            System.out.println(localeList[i].getdisplayCountry() 
+ "=" + localeList[i].getCountry() + " " + localeList[i].getDisplayLanguage() + "=" + localeList[i].getLanguage());
        }

    }

}

    使用国际化的代码如: 

public class Hello{
    
public static void main(String[] args){
        Locale myLocale 
= Locale.getDefault();
        ResourceBundle bundle 
= ResourceBundle.getBundle("mess",myLocale);
        System.out.println(bundler.getString(
"hello"));
    }

}

    如果在资源文件中,存在例如msg = Hello,{0}!Today is {1}.这样需要程序动态插入参数的文本,则需要使用MessageFormat类的format()方法。

    除了使用资源文件,我们也可以使用类文件来代替资源文件。使用Java文件代替资源文件的Java文件必须满足:1。类名必须是baseName_language_country,这与属性文件的命名相似。2。该类必须继承ListResourceBundle,并重写getContents方法,该方法返回Object数组。该数组的每一个项都是key-value对。

public class MyResource_zh_CN extends ListResourceBundle {
    
//定义资源
    private final Object myData[][] = {
        
{"msg","类文件消息:{0},您好!今天是{1}"}
    }
;
    @Override
    
public Object[][] getContents(){
        
return myData;
    }

}


    对于简体中文的Locale,ResourceBundler搜索资源的顺序是:

    baseName_zh_CN.class;baseName_zh_CH.properties;baseName_zh.class;baseName_zh.properties;baseName.class;baseName.properties

 

    Struts2访问国际化消息,主要有3种方式:1)JSP页面输出国际化消息,可以使用Struts2的<s:text.../>标签,该标签可以指定一个name属性,该属性就是资源文件中的key。2)在Action中,可以使用ActionSupport类的getText方法,该方法可以接受一个name参数,指定了国际化资源文件中的key。3)表单元素的Label,可以为表单标签指定一个key属性,这个key指定了国际化资源文件的key。

     对于带占位符的国际化消息,在Action中,则需要使用getText(String key, String[] args)来处理,其中args就是参数列表;而在页面中,则需要为<s:text.../>标签指定<s:param.../>子标签。如:

<s:text name="welcomeMsg">
    
<s:param><s:property value="username"></s:param>
</s:text>


   在Struts2中,还有一种更加简单的表达方式。我们可以在资源文件中写例如这样的表达式:failTip=${username},对不起,您不能登录!,通过使用表达式,可以从ValueStack中取出username属性值,自动填充到消息资源中。这在Action中很常用。

    对于一个大型应用而言,国际化资源文件的管理也是一个非常浩大的工程。为了能更好的分而治之,Struts2允许针对不同的模块、不同Action来组织国家化资源文件。

     为Strut2应用指定包范围资源文件的方法是:在包的跟路径下建立多个文件名为package_language_country.properties的文件,一旦建立了这个系列的国际化资源文件,应用中处于该包下的所有Action都可以访问该资源文件。

    例如一个Action为codes\packageScope\src\lee\action\LoginAction.java,那么我们可以提供package_zh_CN.properties和package_en_US.properties两个文件放在codes\packageScope\src\lee目录下,那么这两个文件就能被lee包及lee包下所有子包内的Action所能访问。

    同时,我们也可以为LoginAction单独指定一份国际化资源文件。即在codes\packageScope\src\lee\action目录下,分别建立LoginAction_zh_CN.properties和LoginAction_en_US.properties两个文件。

    有时候,处于某种特殊的原因,我们需要临时指定资源文件,那么就需要使用<s:i18n.../>来充当<s:text.../>标签的父标签了。如:

<s:i18n name="tmp">
    
<s:text name="loginPage"/>
</s:i18n>

<s:i18n name="tmp">
    
<s:form action="login">
        
<s:textfield name="username" key="user"/>
        
<s:textfield name="password" key="pass"/>
        
<s:submit key="login"/>
    
</s:form>
</s:i18n>


    加载资源文件的顺序:

  1.     优先加载系统中保存在ChildAction的类文件相同位置,且baseName为ChildAction的系列资源文件。
  2.     如果在1)中找不到key对应的消息,且ChildAction有父类ParentAction,则加载系统中保存在ParentAction的类文件相同位置,且baseName为ParentAction的系列资源文件。
  3.     如果2)中找不到key对应的消息,且ChildAction有实现接口IChildAction,则加载系统中保存在IChildAction的类文件相同位置,且baseName为IChildAction的系列资源文件。
  4.     如果3)中找不到key对应的消息,且ChildAction有实现接口ModelDriven(即使用模型驱动模式),则对于getModel()方法返回的model对象,重新执行1)步操作。
  5.     如果在4)中找不到key对应的消息,则查找当前包下baseName为package的系列资源文件。
  6.     如果在5)中找不到key对应的消息,则沿着当前包上溯,直到最顶层包来查找baseName为package的系列资源文件。
  7.     如果在6)中找不到key对应的消息,则查找struts.custom.i18n.resources常量指定baseName的系列资源文件。
  8.     如果经过上面步骤一直找不到key对应的消息,将直接输出该key的字符串值

      对于在JSP中访问国际化消息,则简单很多,可以分为两种形式:

      1)对于使用<s:i18n.../>标签作为父标签的<s:text.../>标签,将直接从<s:i18n.../>标签指定的国际化资源文件中加载指定key对应的消息,如果没有,则读取struts.custom.i18n.resources常量指定baseName的系列文件。如果还没有,直接输出key。

     2)对于没有使用<s:i18n.../>标签作为父标签的<s:text.../>标签,则直接读取struts.custom.i18n.resources常量指定baseName的系列文件。如果没有,直接输出key。

    Struts2中, 我们可以通过ActionContext.getContext().setLocale(Locale arg)设置用户的默认语言。同时在Struts2 的defaultStack拦截栈中,i18n拦截器也能设置默认语言。i18n在执行Action方法前,会自动查找一个名为request_locale的参数。如果这个参数存在,则拦截器会将其转换成Locale对象,并设为默认的Locale。同时,这个Locale对象会保存在Session的名为WW_TRANS_I18N_LOCALE的属性中。一旦用户的Session中有WW_TRANS_I18N_LOCALE属性,则属性指定的Locale将会作为浏览器的默认Locale。因此,用户也可利用此功能来开发自行选择语言的功能。

posted @ 2010-11-11 22:16 Brian 阅读(318) | 评论 (0)编辑 收藏
     摘要:     Struts2默认使用Jakarta的Common-FileUpload的文件上传解析器。见struts.properties配置文件中: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->#指定使用COS的文件上...  阅读全文
posted @ 2010-11-07 14:19 Brian 阅读(465) | 评论 (0)编辑 收藏

    对于login方法的校验,可以通过<ActionClassName>-<ActionAliasName>-validation.xml文件来校验,即RegistAction-login-validation.xml文件进行校验。同时,RegistAction-validation.xml的校验规则仍旧对login方法有效。即login方法的校验规则是Region-validation.xml和RegistAction-login-validation.xml的总和。
    如果RegistAction继承了BaseAction,那么对于BaseAction类的校验规则也会被RegistAction类所继承校验。具体来说,其校验规则的搜索文件规则如下:
        BaseAction-validation.xml
        BaseAction-别名-validation.xml
        RegistAction-validation.xml
        RegistAction-别名-validation.xml

    对于Struts2所支持的内建校验器,我们可以通过xwork.2.1.2.jar中的com/opensymphony/xwork2/validator/validators/default.xml文件查看。

    除了配置文件,Struts2也支持Annotation。下面就是使用Annotation配置的RegistAction:

@Validation()
public class RegistAction extends ActionSupport {
    private static final long serialVersionUID = -2113900523366315993L;
    
    //该请求包含的4个请求参数
    private String name;
    private String pass;
    private int age;
    private Date birth;
    
    
    public String getName() {
        return name;
    }
        @RequiredStringValidator(type=ValidatorType.FIELD,key="name.required",message="")
        @RegexFieldValidator(type=ValidatorType.FIELD,expression="\\w{4,25}",key="name.regex",message="")
    public void setName(String name) {
        this.name = name;
    }
    public String getPass() {
        return pass;
    }
        @RequiredStringValidator(type=ValidatorType.FIELD,key="pass.required",message="")
        @RegexFieldValidator(type=ValidatorType.FIELD,expression="\\w{4,25}",key="pass.regex",message="")
    public void setPass(String pass) {
        this.pass = pass;
    }
    public int getAge() {
        return age;
    }
        @IntRangeFieldValidator(message="",key="age.range",min="1",max="150")
    public void setAge(int age) {
        this.age = age;
    }
    public Date getBirth() {
        return birth;
    }
        @DateRangeFieldValidator(message="",key="birth.range",min="1900/01/01",max="2050/01/21")
    public void setBirth(Date birth) {
        this.birth = birth;
    }
}

     

    对于不能通过内置校验器进行校验的逻辑,则可通过重写validate()方法来实现。如果一个Action中存在多个逻辑处理,则需要通过validateXxx()方法来分别进行校验,其中Xxx代表方法名。如login()方法对应的校验方法为validateLogin()。

    Struts2的输入校验流程:

    1。类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值。

    2。在执行类型转换过程中,如果发生异常,则将异常保存到ActionContext中,并由conversionError拦截器负责将其封装到fieldError里。然后执行第3步;如无异常,直接执行第3步。

    3。调用Struts2内置的输入校验规则进行输入校验

    4。通过放射调用validateXxx()方法。

    5。调用validate()方法。

    6。如果上述都未发生fieldError,将调用Action里处理用户请求的处理方法;如果出现了fieldError,则转入input逻辑视图所指定的视图资源。

posted @ 2010-10-24 15:35 Brian 阅读(469) | 评论 (1)编辑 收藏
     摘要:     Struts2提供了基于验证框架的输入校验,在这种校验方式下,所有的输入校验只需要通过指定的配置文件即可。Struts2中每个Action都有一个校验文件,其规则为:<Action名字>-validation.xml。如: Code highlighting produced by Actipro CodeHighlighter (freewar...  阅读全文
posted @ 2010-10-24 15:01 Brian 阅读(345) | 评论 (0)编辑 收藏
     摘要: Ext.data.Connection     Ext.data.Connection是对Ext.lib.Ajax的封装,它提供了配置使用Ajax的通用方式,它在内部通过Ext.lib.Ajax实现与后台的异步调用。与底层的Ext.lib.Ajax相比,Ext.data.Connection提供了更简洁的配置方式,使用起来更方便。   ...  阅读全文
posted @ 2009-10-27 11:00 Brian 阅读(1388) | 评论 (1)编辑 收藏

公告


导航

<2009年10月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜