Struts2系列:(25) 国际化TextProvider如何搜索ResouceBundle的位置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Struts2系列:(25) 国际化TextProvider如何搜索ResouceBundle的位置相关的知识,希望对你有一定的参考价值。


1、Struts2的默认TextProvider搜索ResouceBundle的(顺序)位置

Struts 2 default TextProvider ResourceBundle location algorithm


在上一个案例中,我们看到properties的名字与aciton class的名字相同,并且放在同一个包下,但这是最简单的一种放置properties文件的位置的方式。

We’ve already seen that the framework looks for bundles that match the name of your current action class. But this is just the tip of the iceberg. We’ll  try  to  provide  a  clear  outline  of  the  process  that  the  framework’s default  TextProvider  goes  through  when  locating  ResourceBundles.  It’s  a  rich model. Essentially, Struts 2 leaves the door wide open for you to distribute the localized text of your application in about any way you see fit. 


除了上述这种最简单的方式,TextProvider接口的默认实现(应该是ActionSupport类)会搜索几个well-known location。这几个位置都遵循similar naming pattern。

In addition to the action-class–named ResourceBundles, the default implementation of TextProvider searches in several other “well-known” locations for bundles that might’ve been created by the developer. Many of these locations follow a similar naming pattern based on the names of superclasses and implemented interfaces. The following sequence shows the name and derivation of the ResourceBundles that Struts 2 attempts to load:


顺序:当前Action类-->实现的Interface-->实现的父类-->ModelDriven-->package.properties-->Domain model-->global bundles


1 ActionClass—Is  there  a  ResourceBundle  with  the  same  name  as  the  current action  class?  In  other  words,  is  there  a  set  of  properties  files  like  ActionClass.properties, ActionClass_en_US.properties, and so forth? 


2 MyInterface—If  your  action  implements  any  interfaces,  are  there  ResourceBundles  associated  with  those  interfaces?  In  other  words,  if  the  current  class implements  MyInterface,  is  there  a  set  of  properties  files  like  MyInterface.properties,  MyInterface_en_US.properties,  and  so  forth?  Superinterfaces  of each interface will also be searched accordingly, with more specific interfaces taking precedence over superinterfaces.


3 MySuperClass—If your action extends a superclass, is there a ResourceBundle associated  with  that  superclass?  In  other  words,  if  the  superclass  is  MySuperClass,  is  there  a  set  of  properties  files  like  MySuperClass.properties, MySuperClass_en_US.properties, and so forth? Note that the search continues up the superclass chain all the way to Object, looking for ResourceBundles all the way. Again, the ResourceBundles of classes lower on the chain take precedence over the higher ones. In other words, Object.properties comes last, if it exists.


4 If the action implements ModelDriven, the class of the model object itself will be used to look up ResourceBundles. In other words, if our model object is our User class, then User.properties, and so on, will be loaded if they exist. Furthermore, the entire process of searching up the interface and class hierarchy, as outlined, will be repeated in the context of the model object class.


5 package.properties—Next, the search tries to load a package ResourceBundle for the package of the current action class, and every superpackage back up the chain.  In  other  words,  if  our  current  action  is  com.rk.struts.i18n.HelloWorldAction, the framework will attempt to find a package.properties file located in the com.rk.struts.i18n package, then in the com.rk.struts package.  Note  that  these  properties  files  are  all  named  package.properties,  and  are located in the directory structure of the package to which they belong.


6 Domain model object exposed on the ValueStack referenced by key—This is similar to #4, ModelDriven. Given a key such as user.username, if the ValueStack has a property exposed on it named user, then the class of that property will be used to load ResourceBundles, again following the same process we’ve outlined. However, when resolving the key against those bundles, the first element of the key is stripped away. In other words, given the key user.username, and a user property  on  the  ValueStack  (of  type  User),  the  ResourceBundles  associated  with User, beginning with the User.properties, will be searched for a message with the key username, not user.username.


7 Default ResourceBundles—Struts 2 allows you to specify global bundles that will always be available.


TextProvider会加载所有能够找到的bundle数据,形成一个look hierarchy用于搜索数据。

All bundles that are found are added to the stock of messages that the TextProvider will make available. The various ResourceBundles that are loaded into the TextProvider form a lookup hierarchy for resolving message keys. 


TextProvider从上往下搜索,遇到的第一个搜索的key值,就返回。

The TextProvider starts at the top of the bundle stack and works its way down. The first bundle, from the top, that can return a value for the key wins.


2、Locale在TextProvider形成bundle hierarchy内起作用

LOCALE SPECIFICITY AND MESSAGE RETRIEVAL


通过上文谈到的properties文件,由TextProvider加载后,形成一个lookup hierarchy。但是,当Locale信息也加入进来,它会对原有的lookup hierarchy的搜索顺序产生影响吗?

When working your way through the bundle search and the text retrieval hierarchy, you might’ve asked yourself how locale influences the retrieval of messages. Of course, if the current locale matches one of the properties files locale extensions, we expect that the text comes from that file’s set of values. If that file doesn’t exist, or if the request key isn’t defined in that file, we must fall through to the next most specific locale match. 


在上面谈到的TextProvider形成bundle hierarchy,不会受到Locale的影响Locale信息只能在由TextProvider形成的的bundle hierarchy的某一层中起作用。TextProvider形成bundle hierarchy起主要作用,而Locale起次要作用。

This locale specificity hierarchy is always used when Struts 2 attempts to locate your message text. However, this algorithm is isolated within a given bundle from the bundle hierarchy outlined previously. Consider that a ResourceBundle associated with an interface takes precedence over a ResourceBundle associated with a superclass. Here’s a quick scenario explaining how locale specificity factors into this. Assume the locale of en_US again. Also, assume that our action implements an interface, MyInterface, and also has a superclass, MySuperClass. Assume too that both the interface and the superclass have properties files associated with them so the framework will create both the MyInterface and the MySuperClass bundles. Now let’s see what happens if we try to resolve the homepage.greeting key.


As we know, this key will first be tried against the interface bundle, according to the search order we’ve outlined. Here’s the question regarding locale specificity. What happens  if  MyInterface  only  has  a  MyInterface.properties  file,  a  default  set  of resources, but MySuperClass has a specific MySuperClass_en_US.properties file? You might think that the more specific locale should win, but it doesn’t. The default message is retrieved from the MyInterface.properties file ahead of the more locale-specific superclass file. This is because locale specificity only matters within the bounds of a given resource bundle, in this case MyInterface. Being higher in the bundle search order trumps locale specificity. 


3、如何注册defautl bundles

DEFINING DEFAULT BUNDLES


Struts2允许我们将properties文件放在“任意”位置,然后再向Struts2中注册properties文件的位置。由我们指定的properties文件被称为default bundles。

The first six steps of the bundle search order outline convention-based locations where Struts 2 will search for properties files. In order to have Struts 2 find your properties files, you must put them where it wants them. The framework, however, does provide you with a way to locate your properties files according to your own whim. This is the role of default bundles.


Default bundles是TextProvider最后查找的properties文件。Default bundles非常的有用,可以被认为是global bundles

Default bundles are great. If none of the convention-oriented bundles exist, such as the action class–associated bundle, there’s always the default bundles. These are the last  place  where  the  framework  will  look  when  trying  to  resolve  a  key.  For  some projects, it might suffice to use default bundles exclusively, filling them with all of the text resources required by your entire application. This is a common practice. Other applications  might  want  to  organize  their  text  resources  according  to  application region  and  package  space.  Within  this  more  hierarchical  organization  of  text resources, you still might find it useful to define globally useful text in a default bundle. Default bundles can, in fact, be thought of as global bundles. 


如果要告诉Struts2存放defautl bundles的位置,可以在struts.properties或struts.xml中设置struts.custom.i18n.resources。

Whatever your use case, defining default bundles is as simple as telling the framework  the  name  of  your  bundles.  To  do  this,  you  just  need  to  set  the  value  for  the Struts 2 property struts.custom.i18n.resources. You can set this, and all Struts 2 properties, either in the struts.properties file or with a constant element in one of your  XML  configuration  files,  for  example  struts.xml  or  one  of  the  files  it  sources. Either way, it doesn’t matter. The following shows the constant element, which can be placed in struts.xml or any other XML sourced by that file:

<constant name="struts.custom.i18n.resources" value="global-messages" />


Here’s the same bit of configuration as done in the struts.properties file:

struts.custom.i18n.resources=global-messages


如果存在多个bundle,可以用“,”分隔。如果bundle存放在某个包中,也需要指定包名

You can specify a comma-separated list of bundles, to be searched in the given order. You can also specify package space for the location of the bundles. Here’s what this would look like:

struts.custom.i18n.resources=global-messages,manning.utils.otherBundle


This  would  look  for  a  properties  file  otherBundle.properties  in  the  manning.util directory space. If for some reason you mix configuration patterns, bear in mind that the struts.properties file trumps the constant element from the XML.




以上是关于Struts2系列:(25) 国际化TextProvider如何搜索ResouceBundle的位置的主要内容,如果未能解决你的问题,请参考以下文章

Struts2-学习笔记系列(13)-类型转换异常和校验器

struts2学习(10)struts2国际化

Struts2的国际化入门

Struts2框架使用之struts2的国际化

struts2国际化

Struts2学习笔记(12)Struts2国际化