Struts2 国际化资源表达式用法--和--properties文件转码

来源:互联网 发布:淘宝修改销量代码 编辑:程序博客网 时间:2024/05/16 01:40

下面略述com.opensymphony.xwork2.ActionSupport.getText()方法public String getText(String aTextName)说明:Gets a messages based on a message key,or null if no message is foundParameters:aTextName-the resource bundle key that is to be searched for得到一个基于key的消息,如果没有找到这个消息则返回null参数:aTextName是在资源包寻找到的所匹配的key小结:该方法用来完成国际化,接收的参数即资源包中的key,返回资源包中的valuepublic String getText(String aTextName,List args)说明:Gets a message based on a key using the supplied args,as defined in MessageFormat使用提供的一个被定义在MessageFormat中的参数args得到一个基于key的消息小结:即此时资源包的key的值可以带参数,即{0}占位符,该参数由List类型的args提供换句话说,此时可以传递一些运行时的参数,使得消息的产生是动态的另外还有个与该方法功能相同的public String getText(String key,String[] args)只不过List参数的方法可接收Object参数,而数组参数的方法则只能接收String实际上Object类型的参数真正输出到页面时,也是调用toString()转换成字符串public String getText(String aTextName,String defaultValue)说明:Gets a message based on a key,if the message is not found,a supplied default value is returned小结:即当在资源包中找不到key时,就会返回defaultValue


Struts2里面国际化资源文件的三个存活范围Struts2提供了更精细化的资源文件定义方式,可分全局的局部的而局部的国际化资源文件又分为两种情况,分别是:包级别类级别包级别资源文件自然要在相应包下建立,它的命名是固定的package_zh_CN.properties若存在相同key,那么包级别中的提示信息要高于全局资源文件中的提示信息这就好似Java一样,若定义了同名的成员变量和局部变量,那么成员变量将被覆盖掉类级别资源文件同样要建立在相应包下,它的命名类似于LoginAction_zh_CN.properties类级别的提示信息更加具体,因此类级别的提示信息要高于包级别资源文件的提示信息


类级别和包级别在应用中的触发点若要在表单中进行国际化信息的显示,则应去掉<s:form/>theme="simple"属性然后将姓名输入域改为<s:textfield name="username" key="username.xml.invalid"/>访问页面时,会在姓名位置显示包级别提示信息,即package_zh_CN.properties中的点击Submit时会在姓名位置显示类级别别提示信息,即RegisterAction_zh_CN.properties中的点击Submit后,表单便与在struts.xml中设定的Action关联在一起,故显示类级别提示信息所以当使用类级别国际化文件时,必须经过Action才能生效,才能按照预定的进行国际化若未经Action而直接访问JSP页面,则无法显示类级别的国际化消息,这一点和Struts1.X是不一样的


在国际化资源文件中嵌套OGNL表达式国际化资源文件中的内容示例如下login.text = 登录login.title = %{getText("login.text")}页面那么在页面中显示login.title国际化消息时,就会显示:登录页面


页面中国际化的显示<s:text name="key"/>会自动按照范围到资源文件中查找name所指定的key然后输出Key所对应的Value,若Key不存在,则将name值原封不动的输出并且它也是可以动态传递参数的,这时需要在该标签中嵌套<s:param/>标签<s:label key=""/>在输出国际化信息时,会自动在国际化文本后面加上一个多余的冒号通过查看页面源文件发现:使用<s:label/>输出的国际化信息位于HTML的<label/>标签内使用<s:text/>输出的国际化信息则是一些单纯的文本<s:i18n name=""/>用来明确的指定所使用的临时的国际化资源文件并且该临时资源文件默认与struts.xml处于同一目录下,亦可在name中指定其存放路径它的name值用来指定所要读取的国际化资源文件,然后再嵌套<s:text/>标签就可以输出指定的key值了在<s:param/>中显示国际化信息如在<s:param value="%{getText('login.tip')}"/><s:param/>中接收Action属性如<s:param value="%{username}"/>Struts2表单标签的key属性通常用来输出国际化信息,可以在key值中传一个OGNL表达式而label属性中放的是字符串,所以也可以使用%{}输出国际化信息,如下所示<s:property value="getText('key')"/>或者<s:textfield label="%{getText('key')}"/>另外关于<s:radio/>标签的国际化显示,如下所示<s:radio list="#{1:getText('i18n.sex.male') ,0:getText('i18n.sex.female')}" name="sex" value="1" key="i18n.sex"/>这个时候就不用再写成%{getText('i18n.sex.male')}了,也就是说可以把%{}去掉了由于<s:textfield label="%{getText('key')}"/>label默认使用的是字符串,所以要加上%{}而在<s:radio/>list属性里面本身已经有{}符号了,说明它已经是一个OGNL表达式了所以在<s:radio list=“#{}”/>中就没必要再使用%{}


浅述Struts2国际化的实现过程Struts2的I18nInterceptor拦截器会拦截所有的Action,它主要做的事情为从客户端发送过来的请求参数中寻找是否存在名为request_locale的参数若有,则将request_locale的value转化为locale保存起来该locale是保存在以WW_TRANS_I18N_LOCALE所命名的session里面的详见源码的第124行session.put(attributeName, locale)其中attributeName即79行的protected String attributeName = DEFAULT_SESSION_ATTRIBUTE和第75行的public static final String DEFAULT_SESSION_ATTRIBUTE = "WW_TRANS_I18N_LOCALE"于是便可通过这种方式实现一个选择页面所显示的语言环境的功能比如选择中文,那么就可以将request_locale设置为zh_CN如果我们不做任何配置的话,客户端是不会发送request_locale参数的它默认会用request的getLocale()方法得到默认locale,将其存放在session中这样就使得以后客户的所有操作都是在同一个国际化的环境下执行就不需要我们每一次都手工判断用户的国际化环境了


接下来为大家展示示例代码

首先是struts.xml文件

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
  3. "http://struts.apache.org/dtds/struts-2.1.dtd">
  4. <struts>
  5. <constant name="struts.custom.i18n.resources" value="message"/>
  6. <package name="struts2.1" extends="struts-default">
  7. <action name="internationalization" class="com.jadyer.action.InternationalizationAction">
  8. <result>loginSuccess.jsp</result>
  9. <result name="input">internationalization.jsp</result>
  10. </action>
  11. </package>
  12. </struts>

然后是web.xml文件

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  6. <filter>
  7. <filter-name>struts2</filter-name>
  8. <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>struts2</filter-name>
  12. <url-pattern>/*</url-pattern>
  13. </filter-mapping>
  14. <welcome-file-list>
  15. <welcome-file>internationalization.jsp</welcome-file>
  16. </welcome-file-list>
  17. </web-app>

用于显示国际化信息的internationalization.jsp页面

[xhtml] view plaincopy
  1. <%@ page language="java" pageEncoding="UTF-8"%>
  2. <%@ taglib prefix="s" uri="/struts-tags"%>
  3. <strong>
  4. <a href="internationalization.action?request_locale=zh_CN"><s:text name="internationalization.jsp.CHINESE"/></a>|
  5. <a href="internationalization.action?request_locale=en_US"><s:text name="internationalization.jsp.ENGLISH"/></a>
  6. </strong>
  7. <hr/>
  8. <STRONG>
  9. <FONT color="green">
  10. <s:i18n name="com.jadyer.action.temp">
  11. <s:text name="hello">
  12. <s:param>玄玉</s:param>
  13. </s:text>
  14. </s:i18n>
  15. </FONT>
  16. </STRONG>
  17. <hr/>
  18. <h4>初始姓名和密码为<font color="blue"><b>admin</b></font><font color="blue"><b>jadyer</b></font></h4>
  19. <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold"/>
  20. <s:form action="internationalization" theme="simple">
  21. <table border="9">
  22. <tr>
  23. <td><s:property value="getText('internationalization.jsp.username')"/></td>
  24. <td><s:textfield name="username"/></td>
  25. </tr>
  26. <tr>
  27. <td><s:text name="internationalization.jsp.passwrod"/></td>
  28. <td><s:password name="password"/></td>
  29. </tr>
  30. <tr>
  31. <td> </td>
  32. <td align="center"><s:submit/></td>
  33. </tr>
  34. </table>
  35. </s:form>

访问成功后跳转到loginSuccess.jsp页面

[xhtml] view plaincopy
  1. <%@ page pageEncoding="UTF-8"%>
  2. <h2>Login Success</h2>

然后是用到的InternationalizationAction.java类

[java] view plaincopy
  1. package com.jadyer.action;
  2. import com.opensymphony.xwork2.ActionSupport;
  3. @SuppressWarnings("serial")
  4. public class InternationalizationAction extends ActionSupport {
  5. private String username;
  6. private String password;
  7. //关于username和password属性的getter和setter方法略
  8. @Override
  9. public String execute() throws Exception {
  10. if("admin".equals(this.getUsername().trim())&&"jadyer".equals(this.getPassword().trim())){
  11. return SUCCESS;
  12. }else{
  13. this.addFieldError("username"this.getText("username.password.error"));
  14. return INPUT;
  15. }
  16. }
  17. /**
  18. * List list = new ArrayList();
  19. * list.add(username);
  20. * this.addFieldError(this.getText("username.invalid", list));
  21. * 建议使用String[]数组的方式。因为它本身放的就是String类型的参数,很方便
  22. * 使用addActionError()实现国际化的方式与addFieldError()是一样的,这里就不再举例了
  23. */
  24. @Override
  25. public void validate() {
  26. if (null == username || username.length() < 4 || username.length() > 10) {
  27. this.addFieldError("username",this.getText("username.invalid"new String[]{username}));
  28. }
  29. }
  30. }

用来测试<s:i18n>、<s:text>、<s:param>标签组合使用的temp_zh_CN_en_US.properties国际化资源文件

[c-sharp] view plaincopy
  1. hello = /u4F60/u597D/u3010{0}/u3011/u3002/u8FD9/u662F/u4F7F/u7528Struts2/u7684i18n/u6807/u7B7E/u5D4C/u5957text/u6807/u7B7E/u8F93/u51FA/u7684/u7ED3/u679C
  2. hello = Hello/u3010{0}/u3011/u3002This is used the Struts2 i18n with text tag to result

最后是用到的全局的message_zh_CN.properties和message_en_US.properties国际化资源文件

[java] view plaincopy
  1. internationalization.jsp.CHINESE = /u4E2D/u6587/u7248
  2. internationalization.jsp.ENGLISH = /u82F1/u6587/u7248
  3. internationalization.jsp.passwrod = /u5BC6/u7801
  4. internationalization.jsp.username = /u7528/u6237
  5. username.invalid = /u7528/u6237/u540D "{0}" /u586B/u5199/u4E0D/u6B63/u786E
  6. username.password.error = /u7528/u6237/u540D/u6216/u5BC6/u7801/u4E0D/u6B63/u786E
  7. internationalization.jsp.CHINESE = Chinese
  8. internationalization.jsp.ENGLISH = English
  9. internationalization.jsp.passwrod = password
  10. internationalization.jsp.username = username
  11. username.invalid = username "{0}" invalid
  12. username.password.error = username or password error
在命令行界面用native2ascii工具  
1.将汉字转为Unicode:
C:\Program Files\Java\jdk1.5.0_04\bin>native2ascii
测试
\u6d4b\u8bd5
2.将Unicode转换为汉字:
C:\Program Files\Java\jdk1.5.0_04\bin>native2ascii -reverse
\u6d4b\u8bd5
测试

java 自带的一个native2ascii.exe是一个很好的转码工具,在bin目录下。如果你的properties中有汉字,需要转成unicode . 则把含有汉字的properties拷贝到bin 目录下, 然后在cmd里面进入bin目录,输入:native2ascii -encoding utf-8 Language-ext_zh_CN.properties.native Language-ext_zh_CN.properties就ok了。Language-ext_zh_CN.properties是转码后的文件。

在做Java开发的时候,常常会出现一些乱码,或者无法正确识别或读取的文件,比如常见的validator验 证用的消息资源(properties)文件就需要进行Unicode重新编码。原因是java默认的编码方式为Unicode,而我们的计算机系统编码 常常是GBK等编码。需要将系统的编码转换为java正确识别的编码问题就解决了。

1、native2ascii简介:native2ascii 是sun java sdk提供的一个工具。用来将别的文本类文件(比如*.txt,*.ini,*.properties,*.java等等)编码转为Unicode编码。 为什么要进行转码,原因在于程序的国际化。Unicode编码的定义:Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每 种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算 机工作能力的增强,Unicode也在面世以来的十多年里得到普及。(声明:Unicode编码定义来自互联网)。

2、获取native2ascii:安装了jdk后,假如你是在windows上安装,那么在jdk的安装目录下,会有一个bin目录,其中native2ascii.exe正是。

3、native2ascii的命令行的命名格式:
native2ascii -[options] [inputfile [outputfile]]

说明:
-[options]:表示命令开关,有两个选项可供选择
-reverse:将Unicode编码转为本地或者指定编码,不指定编码情况下,将转为本地编码。
-encoding encoding_name:转换为指定编码,encoding_name为编码名称。
[inputfile [outputfile]]
inputfile:表示输入文件全名。
outputfile:输出文件名。如果缺少此参数,将输出到控制台。
4、最佳实践:首先将JDK的bin目录加入系统变量path。在盘下建立一个test目录,在test目录里建立一个zh.txt文件,文件内容为:“熔岩”,打开“命令行提示符”,并进入C:\test目录下。下面就可以按照说明一步一步来操作,注意观察其中编码的变化。

A:将zh.txt转换为Unicode编码,输出文件到u.txt
native2ascii zh.txt u.txt
打开u.txt,内容为“\u7194\u5ca9”。
B:将zh.txt转换为Unicode编码,输出到控制台
C:\test>native2ascii zh.txt
\u7194\u5ca9
可以看到,控制台输出了“\u7194\u5ca9”。
C:将zh.txt转换为ISO8859-1编码,输出文件到i.txt
native2ascii -encoding ISO8859-1 zh.txt i.txt
打开i.txt文件,内容为“\u00c8\u00db\u00d1\u00d2”。
D:将u.txt转换为本地编码,输出到文件u_nv.txt
native2ascii -reverse u.txt u_nv.txt
打开u_nv.txt文件,内容为“熔岩”。
E:将u.txt转换为本地编码,输出到控制台
C:\test>native2ascii -reverse u.txt
熔岩
可以看到,控制台输出了“熔岩”。
F:将i.txt转换为本地编码,输出到i_nv.txt
native2ascii -reverse i.txt i_nv.txt
打开i_nv.txt文件,内容为“\u00c8\u00db\u00d1\u00d2”。发现转码前后完全一样的。也就是说,等于没有转,或者说思想糊涂,对命名没有理解。。

G:将i.txt转换为GBK编码,输出到i_gbk.txt
native2ascii -reverse -encoding GBK i.txt i_gbk.txt
打开i_gbk.txt文件,内容为“\u00c8\u00db\u00d1\u00d2”。发现转码前后完全一样的。也就是说,等于没有转,或者说思想糊涂,对命名没有理解。

H:将u_nv.txt转码到本地编码GBK,输出到控制台
C:\test>native2ascii -reverse -encoding ISO8859-1 i.txt
熔岩
从这个结果看,目标达到到了,编码i.txt为ISO8859-1,转为本地编码后内容为“熔岩”。从这里应该意识到,native2ascii -reverse命令中-encoding指定的编码为源文件的编码格式。而在native2ascii 命令中-encoding指定的编码为(生成的)目标文件的编码格式。这一点非常的重要!切记!!

继续探索,新建文件12a.txt,内容“12axyz”。看看纯字母数字的编码又如何。

I:将纯字母数字的文本文件12a.txt转换为Unicode编码
native2ascii 12a.txt 12a_nv.txt
打开12a_nv.txt文件,内容为“12axyz”。
继续测试,转为ISO8859-1编码看看
C:\test>native2ascii -encoding ISO8859-1 12a.txt
12axyz
结果还是没有转码。
从结果可以得出结论:对于纯数字和字母的文本类型件,转码前后的内容是一样的。
0 0
原创粉丝点击