欢迎光临
我们一直在努力

Struts应用的国际化-JSP教程,资料/其它

建站超值云服务器,限时71元/月
struts应用的国际化
万维网(world wide web)的迅猛发展推动了跨国业务的发展,它成为一种在全世界范围内发布产品信息、吸引客户的有效手段。为了使企业web应用能支持全球客户,软件开发者应该开发出支持多国语言、国际化的web应用。
 
1 本地化与国际化的概念
国际化(简称为i18n)指的是软件设计阶段,就应该使软件具有支持多种语言和地区的功能。这样,当需要在应用中添加对一种新的语言和国家的支持时,不需要对已有的软件返工,无需修改应用的程序代码。
本地化意味着针对不同语言的客户,开发出不同的软件版本;国际化意味着同一个软件可以面向使用各种不同语言的客户。
如果一个应用支持国际化,它应该具备以下特征:
· 当应用需要支持一种新的语言时,无需修改应用程序代码。
· 文本、消息和图片从源程序代码中抽取出来,存储在外部。
· 应该根据用户的语言和地理位置,对与特定文化相关的数据,如日期、时间和货币,进行正确的格式化。
· 支持非标准的字符集。
· 可以方便快捷地对应用作出调整,使它适应新的语言和地区。
 
在对一个web应用进行国际化时,除了应该对网站上的文本、图片和按钮进行国际化外,还应该对数字和货币等根据不同国家的标准进行相关的格式化,这样才能保证各个国家的用户都能顺利地读懂这些数据。
locale(本地)指的是一个具有相同风俗、文化和语言的区域。如果一个应用没有事先把i18n作为那前的功能,那么当这个应用需要支持新的locale时,开发人员必需对嵌入在源代码中的文本、图片和消息进行修改,然后重新编译源代码。每当这个应用需要支持新的locale时,就必需重复这些繁琐的步骤,这种做法显然大大降低了软件开发效率。
 
2 web应用的中文本地化
无论时对web应用的本地化还是国际化,都会涉及字符编码转换问题。当数据流的源与目的地使用不同的字符编码时,就需要对字符编码进行正确的转换。
 
2.1 处理http请求数据编码
    默认情况下,ie浏览器发送请求时采用“iso-8859-1”字符编码,如果web应用程序要正确地读取用户发送的中文数据,则需要进行编码转换。
    一种方法是在处理请求前,先设置httpservletrequest对象的字符编码:
              request.setcharacterencoding(“gb2312”);
    还有一种办法是对用户输入的请求数据进行编码转换:
              string clientdata = request.getparameter(“clientdata”);
              if(clientdata != null)
                     clientdata = new string(clientdata.getbytes(“iso-8859-1”), “gb2312”);
 
2.2 处理数据库数据编码
    如果数据库系统的字符编码为“gb2312”,那么可以直接读取数据库中的中文数据,而无需进行编码转换。如果数据库字符编码为“iso-8859-1”,那么必需先对来自数据库的数据进行编码转换,然后才能使用。
 
2.3 处理xml配置文件编码
    如果在xml文件中包含中文,可以将xml文件的字符编码为“gb2312”。这样,当java程序加载和解析xml文件时无需再进行编码转换。
              <?xml version=’1.0’ encoding=”gb2312”?>
 
2.4 处理响应结果的编码
    可以通过以下方式来设置响应结果的编码:
       · 在servlet中
              response.setcontenttype(“text/html;charset=gb2312”);
       · 在jsp中
              <%@ page contenttype=”text/html;charset=gb2312” %>
       · 在html中
              <head>
       <meta http-equiv=”content-type” content=”text/html; charset=gb2312”>
              </head>
 
3 java对i18n的支持
java在其核心库中提供了支持i18n的类和接口。struts框架依赖于这些java i18n组件来实现对i18n的支持,因此,掌握java i18n组件的使用方法有助于理解struts应用的国际化机制。
3.1 locale类
    java.util.locale类时最重要的java i18n类,在java语言中,几乎所有对国际化和本地化的支持都依赖于这个类。
locale类的实例代表一种特定的语言和地区。如果java类库中的某个类在运行时需要根据locale对象来调整其功能,那么就称这个类是本地敏感的(locale-sensitive)。例如,java.text.dateformat类就是本地敏感的,因为它需要依照特定的locale对象来对日期进行相关的格式化。
locale对象本身病不执行和i18n相关的格式化或解析工作。locale对象仅仅负责向本地敏感的类提供本地化信息。例如,dateformat类依据locale对象来确定日期的格式,然后对日期进行语法分析和格式化。
创建locale对象时,需要明确地指定其语言和国家代码。如:
       locale uslocale = new locale(“en”, “us”);
       locale chlocale = new locale(“ch”, “ch”);
构造方法的第一个参数是语言代码。语言代码由两个小写字母组成,遵从iso-639规范。可以从http://www.unicode.org/unicode/onlinedat/languages.html中获得完整的语言代码列表。
构造方法的第二个参数是国家代码,它由两个大写字母组成,遵从iso-3166规范。可以从http://www.unicode.org/unicode/onlinedat/countries.html中获得完整的国家代码列表。
locale类提供了几个静态常量,他们代表一些常用的locale实例。例如,如果要获得japanese locale实例,可以使用如下两种方法之一:
       locale locale1 = locale.japan;
       locale locale2 = new locale(“ja”, “jp”);
 
3.1.1 web容器中locale对象的来源
    java虚拟机在启动时会查询操作系统,为运行环境设置默认的locale。java程序可以调用java.util.locale类的静态方法getlocale()来获得默认的locale:
              locale defaultlocale = locale.getdefault();
    web容器在其本地环境中通常会使用以上默认的locale;而对于特定的中断用户,web容器会从http请求中获取locale信息。
 
3.1.2 在web应用中访问locale对象
    在创建locale对象时应该把语言和国家代码两个参数传递给构造方法。对于web应用程序,通常不必创建自己的locale实例,因为web容器会负责创建所需的locale实例。在应用程序中,可以调用httpservletrequest对象的以下两个方法,来取得包含web客户的locale信息的locale实例:
              public java.util.locale getlocale();
              public java.util.enumeration getlocales();
    着两个方法都会访问http请求中的accept-language头信息。getlocale()方法返回客户优先使用的locale,而getlocales()方法返回一个enumeration集合对象,它包含了按优先级降序排列的所有locale对象。如果客户没有配置任何locale,getlocale()方法将会返回默认的locale。
 
3.1.3 在struts应用中访问locale对象
    有序web服务器并不和客户浏览器保持长期的连接,因此每个发送到web容器的http请求中都包含了locale信息。struts配置文件的<controller>元素的locale属性指定是否把locale对象保存在session范围中,默认值为true,表示会把locale对象保存在session范围中。在处理每一个用户请求时,requestprocessor类都会调用它的processlocale()方法。
    尽管每次发送的http请求都包含locale信息,processlocale()方法把locale对象存储在session范围中必需满足以下条件:
    · struts配置文件的<controller>元素的locale属性为true。
    · 在session范围内locale对象还不存在。
    processlocale()方法把locale对象存储在session范围中时,属性key为globals.locale_key,这个常量的字符串值为“org.apache.struts.action.locale”。
    如果应用程序允许用户在同一个会话中改变locale,那么应该对每一个新的httpservletrequest调用其getlocale()方法,来判断用户是否改变了locale,如果locale发生改变,就把新的locale对象保存在session范围内。
    在struts应用程序中可以很方便地获取locale信息。例如,如果在action类中访问locale信息,可以调用在struts action基类中定义的getlocale()方法。
    action类的getlocale()方法调用requestutils.getuserlocale()方法。
    getuserlocale()方法先通过httpservletrequest参数获得httpsession对象,然后再通过httpsession对象来读取locale对象。如果存在httpsession对象并且httpsession中存储了locale对象,就返回该locale对象,否则就直接调用httpservletrequest的getlocale()方法取得locale对象,并降它返回。
    在web应用程序的其他地方也可以直接调用requestutils类的getuserlocale()方法来获取locale对象。
 
3.2 resourcebundle类
    java.util.resourcebundle类提供存放和管理与locale相关的资源的功能。这些资源包括文本域或按钮的label、状态信息、图片名、错误信息和网页标题等。
    struts框架并没有直接使用java语言提供的resourcebundle类。在struts框架中提供了两个类:
    · org.apache.struts.util.messageresources
    · org.apache.struts.util.propertymesasgeresources
    这两个类具有和resourcebundle相似的功能,其中propertymessageresources是messageresources类的子类。
 
3.3 messageformat类和符合消息。
    java的resourcebundle和struts的messageresources类都允许使用静态和动态的文本。静态文本指定的是实现就已经具有明确内容的文本。动态文本指的是只有在运行时才能确定内容的文本。
    通常把包含可变数据的消息成为符合消息。符合消息允许在程序运行时把动态数据加入到消息文本中。着能够减少resource bundle中的静态消息数量,从而减少把静态消息文本翻译成其他locale版本所花费的时间。
    当然,在resource bundle中使用符合信息会使文本的翻译变得更加困难。因为文本包含了直到运行时才知道的替代值,而把包含替代值的消息文本翻译成不同的语言时,往往要对语言做适当调整。
    struts框架封装了messageformat类的功能,支持复合消息文本,该功能的实现对于struts的其他组件是透明的。
 
4 struts框架对国际化的支持
struts框架对国际化的支持体现在能够输出何用户locale相符合的文本何图片上。当struts配置文件的<controller>元素的locale属性为true时,struts框架把用户的locale实例保存在session范围内,这样,struts框架能自动根据这一lcoale实例来从resource bundle中选择合适的资源文件。当用户的locale为英文时,struts框架就会向用户返回来自于application_en.properties文件的文本内容:当用户的locale为中文时,struts框架就会向用户返回来自于appcation_ch.properties文件的文本内容。
4.1 创建struts的resource bundle
    对于多应用模块的struts应用,可以为每个子应用配置一个或多个resource bundle,应用模块中的action、actionform bean、jsp页和客户化标签都可以访问这些bundle。struts配置文件中的每个<message-resources>元素定义了一个resource bundle。当应用中包含多个resource bundle时,它们通过<message-resources>元素的key属性来区别。
resource bundle的持久化消息文本存储在资源文件中,其扩展名为“.properties”,这一文件中消息的格式为:key=value。
在创建resource bundle的资源文件时,可以先提供一个默认的资源文件,默认资源文件应该取名为application.properties。如果应用程序需要支持中文用户,可以再创建一个包含中文消息的资源文件,文件名为:application_ch_ch.properties或application_ch.properties。
当struts框架处理locale为中文的用户请求时,struts框架首先在web-inf/classes/目录下寻找application_ch_ch.properties文件,如果存在该文件,就从该文件中获取文本消息,否则再一次寻找application_ch.properties和application.properties文件。
应该总是为resource bundle提供默认的资源文件,这样,当不存在和某个locale对应的资源文件时,就可以使用默认的资源文件。
应该把resource bundle的资源文件放在能被定位并加载的位置。对于web应用程序,资源文件的存放目录为web-inf/classes目录。如果在配置resource bundle时还给定了包名,那么包名应该和资源文件所在的子目录对应。
4.2 访问 resource bundle
    struts应用的每个resource bundle和org.apache.struts.util.messageresources类(实际上是其子类propertymessageresources)的一个实例对应。messageresources对象中存放了来自资源文件的文本。当应用程序初始化时,这些messageresources实例被存储在servletcontext中(即application范围内),因此任何一个web组件都可以访问它们。一个messageresources对象可以包含多种本地化版本的资源文件的数据。
    struts应用、子应用模块、resource bundle和资源文件之间存在以下关系:
    · 一个struts应用可以有多个子应用模块,必须有且只有一个默认子应用模块。
    · 一个子应用模块可以有多个resource bundle,必须有且只有一个默认的resource bundle。
    · 一个resource bundle可以有多个资源文件,必须有且只有一个默认资源文件。
 
    下面介绍在struts应用中访问resource bundle的途径。
<!–[if !supportlists]–>1.  <!–[endif]–>通过编程来访问resource bundle
在action积累中定义了getresources(request)方法,它可以返回默认的message resources对象,代表当前应用模块使用的默认resource bundle。如果要活得特定的messageresources对象,可以调用action基类的getresources(request, key)方法,其中参数key和struts配置文件中的<message-resources>元素的key属性对应。得到了messageresources对象后,就可以通过它的方法来访问消息文本。
org.apache.struts.util.messageresources的getmessage()方法有好几种重载形式,下面列出常用的几种:
· 根据参数置顶的locale检索对应的资源文件,然后返回和参数key对应的消息文本:
getmessage(java.util.locale locale, java.lang.string key)
· 根据参数指定的locale检索对应的资源文件,然后返回和参数key对应的消息文本,args参数用于替换复合消息文本中的参数:
getmessage(java.util.locale locale, java.lang.string key, java.lang.object[] args)
· 根据默认的locale检索对应的资源文件,然后返回和参数key对应的消息文本:
getmessaeg(java.lang.string key)
<!–[if !supportlists]–>2.  <!–[endif]–>使用和resource bundle绑定的struts组件
struts框架中的许多内在组件和resource bundle是绑定在一起的,如:
· actionmessage类和<html:errors>标签。
每个actionmessage实例代表resource bundle中的一条消息。在调用actionmessage的构造方法时,需要传递消息key。
对于复合消息,在创建actionmessage对象时,可以调用带两个参数的构造方法:actionmessage(java.lang.string key, java.lang.object[] values),values参数用户替换复合消息中的参数。
在jsp页面中,使用<html:errors>标签,就能读取并显示actionerrors集合中所有actionmessage对象包含的消息文本。
· struts bean标签库的<bean:message>标签。
        struts框架包含了一些可以访问应用的消息资源的客户化标签,其中使用最频繁的一个标签为<bean:message>标签。<bean:message>标签从应用的resource bundle中获取消息字符串。
        <bean:message>有一个bundle属性,用于指定被访问的resource bundle,它和<message-resources>元素的key属性匹配。如果没有设置bundle属性,将访问默认的resource bundle。
· 在validator验证框架中访问resource bundle。
· 在声明型异常处理中访问resource bundle。
 
5 异常处理的国际化
在处理异常时,也应该考虑对i18n的支持。除非已经对应用抛出的异常消息做本地化,否则不应该直接向终端用户展示原始的异常消息。不懂java语言的终端用户很难理解从java虚拟机堆栈中抛出的java异常消息,如果这些异常消息使用的不是用户的本地语言,那就更加会让用户困惑不解。
应该先把异常捕获,对异常消息进行本地化后,再把它展示给用户。struts的resource bundle和actionmessage类可以完成这一功能。直接向终端用户显示java异常绝对是不可取的。即使发生了无法恢复的系统错误,也应该向用户显示本地化的系统错误页。
 
6 小结
本文档介绍了软件的本地化与国际化的概念,然后消息介绍了对struts应用实现国际化的原理和方法。与国际化密切相关的两个组件是locale和resource bundle:
· locale:包含了用户的本地化信息,如语言和国家。
· resource bundle:包含了多个消息资源文件,每个消息资源文件存放和一种locale相对应的本地化消息文本。
struts框架的初始化时,把resource bundle(即messageresources对象)存储在application范围内;在响应用户请求时,把包装用户locale信息的locale实例存储在session范围内。struts框架能自动根据这一locale实例,从resource bundle中检索相应的资源文件,再从资源文件中读取本地化的消息文本。
对struts应用实现国际化应该遵循以下原则:
· 尽量不在servlet中使用含非英文字符的常量字符串。
· 对于jsp文件,应该对page指令中的charset属性进行相应的设置。
· 不要在jsp文件中直接包含本地化的消息资源,儿应该把消息资源存放在resource bundle的资源文件中。
· 不比在每个jsp或servlet中设置http请求的字符编码,可以在servlet过滤器中设置编码:
   httpservletrequest.setcharaterencoding(string encoding);
· 尽量使用“utf-8”作为http请求和响应的字符编码,而不是“gbk”或“gb2312”。
· 充分考虑底层数据库所使用的编码,它可能会给应用程序的移植带来麻烦。
赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » Struts应用的国际化-JSP教程,资料/其它
分享到: 更多 (0)