码迷,mamicode.com
首页 > 其他好文 > 详细

消息处理与国际化

时间:2015-04-07 15:21:27      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

Struts2 国际化是建立在 Java 国际化基础上的:
                                                                 为不同国家/语言提供对应的消息资源文件
                                                                 Struts2 框架会根据请求中包含的
                                                                 Locale 加载对应的资源文件
                                                                 通过程序代码取得该资源文件中
                                                                 指定 key 对应的消息
书写:i18n_en_US.properties或i18n_zh_CN.properties
 
配置国际化资源文件
Action 范围资源文件:在Action类文件所在的路径建立名为ActionName_language_country.properties 的文件
包范围资源文件:在包的根路径下建立文件名为package_language_country.properties 的属性文件,一旦建立,处于该包下的所有 Action 都可以访问该资源文件。注意:包范围资源文件的 baseName 就是package,不是Action所在的包名。
全局资源文件
命名方式: basename_language_country.properties
struts.xml<constant name="struts.custom.i18n.resources" value="baseName"/>
struts.propertiesstruts.custom.i18n.resources=baseName
临时指定资源文件:<s:i18n.../> 标签的 name 属性指定临时的国际化资源文件
 
 
加载资源文件的顺序
 
假设我们在某个 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的字符串值。
 
SP 页面访问国际化消息:
不带占位符:
<s:text name="key"/>
表单元素的 label 属性:可替换为 key 或使用 getText() 方法,并对其进行强制 OGNL 解析
带占位符:
在 <s:text.../> 标签中使用多个 <s:param.../> 标签来填充消息中的占位符。
Struts2 直接在国际化消息资源文件中通过 “${}” 使用表达式,该表达式将从值栈中获取对应的属性值
 技术分享
访问国际化消息
Action 访问国际化消息:
若 Action 类继承了 ActionSupport ,则可调用 TextProvider 接口的 getText 方法。
 
利用超链接实现动态加载国际化资源文件
 
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 对象。
 
 
 
访问国际化消息 源码解析
 
  1 public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
  2  
  3     private transient TextProvider textProvider ;
  4     private Container container;
  5  
  6     public Locale getLocale() {
  7         ActionContext ctx = ActionContext. getContext();
  8         if (ctx != null ) {
  9             return ctx.getLocale();
 10         } else {
 11             if (LOG .isDebugEnabled()) {
 12            LOG.debug("Action context not initialized" );
 13             }
 14             return null ;
 15         }
 16     }
 17       //当调用这个方法时会调用TextProviderSupport的getText方法
 18     public String getText(String aTextName) {
 19         return getTextProvider().getText(aTextName);
 20     }
 21 }
 22 
 23 public class TextProviderSupport implements ResourceBundleTextProvider {
 24 
 25     private Class clazz;
 26     private LocaleProvider localeProvider;
 27     private ResourceBundle bundle;
 28 
 29     public String getText(String key) {
 30         return getText(key, key, Collections.emptyList());
 31     }
 32 
 33  public String getText(String key, String defaultValue, List<?> args) {
 34         Object[] argsArray = ((args != null && !args.equals(Collections.emptyList())) ? args.toArray() : null);
 35         if (clazz != null) {
 36           //在这里进行读取.加载资源文件的顺序
 37             return LocalizedTextUtil.findText( clazz, key, getLocale(), defaultValue, argsArray);
 38         } else {
 39             return LocalizedTextUtil.findText( bundle, key, getLocale(), defaultValue, argsArray);
 40         }
 41     }
 42 }
 43 在LocalizedTextUtil中调用的方法加载资源文件
 44 public static String findText (Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args,
 45                                   ValueStack valueStack) {
 46         String indexedTextName = null;
 47         if (aTextName == null) {
 48             if (LOG .isWarnEnabled()) {
 49            LOG.warn("Trying to find text with null key!" );
 50             }
 51             aTextName = "";
 52         }
 53         (1)加载和 ChildAction 的类文件在同一个包下的系列资源文件 ChildAction.properties
 54                     (2)加载  ChildAction 实现的接口 IChild,且和 IChildn 在同一个包下 IChild.properties 系列资源文件。
 55                     (3)加载 ChildAction 父类 Parent,且和 Parent 在同一个包下的 baseName 为 Parent.properties 系列资源文件
 56         if (aTextName.contains("[" )) {
 57             int i = -1;
 58 
 59             indexedTextName = aTextName;
 60 
 61             while ((i = indexedTextName.indexOf("[" , i + 1)) != -1) {
 62                 int j = indexedTextName.indexOf("]" , i);
 63                 String a = indexedTextName.substring(0, i);
 64                 String b = indexedTextName.substring(j);
 65                 indexedTextName = a + "[*" + b;
 66             }
 67         }
 68 
 69         // search up class hierarchy
 70         String msg = findMessage(aClass, aTextName, indexedTextName, locale, args, null , valueStack);
 71 
 72         if (msg != null ) {
 73             return msg;
 74         }
 75       若 ChildAction 实现 ModelDriven 接口,则对于getModel()方法返回的model 对象,重新执行第(1)步操作。
 76         if (ModelDriven.class.isAssignableFrom(aClass)) {
 77             ActionContext context = ActionContext.getContext();
 78             
 79             ActionInvocation actionInvocation = context.getActionInvocation();
 80  
 81             if (actionInvocation != null) {
 82                 Object action = actionInvocation.getAction();
 83                 if (action instanceof ModelDriven) {
 84                     Object model = ((ModelDriven) action).getModel();
 85                     if (model != null) {
 86                         msg = findMessage(model.getClass(), aTextName, indexedTextName, locale, args, null, valueStack);
 87                         if (msg != null ) {
 88                             return msg;
 89                         }
 90                     }
 91                 }
 92             }
 93         }
 94 
 95        
 96         for (Class clazz = aClass;
 97              (clazz != null) && !clazz.equals(Object.class );
 98              clazz = clazz.getSuperclass()) {
 99 
100             String basePackageName = clazz.getName();
101             while (basePackageName.lastIndexOf(‘.‘ ) != -1) {
102                 basePackageName = basePackageName.substring(0, basePackageName.lastIndexOf(‘.‘ ));
103                 String packageName = basePackageName + ".package";
104                 msg = getMessage(packageName, locale, aTextName, valueStack, args);
105 
106                 if (msg != null ) {
107                     return msg;
108                 }
109 
110                 if (indexedTextName != null) {
111                     msg = getMessage(packageName, locale, indexedTextName, valueStack, args);
112 
113                     if (msg != null ) {
114                         return msg;
115                     }
116                 }
117             }
118         } 
119         int idx = aTextName.indexOf("." );
120 
121         if (idx != -1) {
122             String newKey = null;
123             String prop = null;
124 
125             if (aTextName.startsWith(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX )) {
126                 idx = aTextName.indexOf( ".", XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX .length());
127 
128                 if (idx != -1) {
129                     prop = aTextName.substring(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX .length(), idx);
130                     newKey = XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX + aTextName.substring(idx + 1);
131                 }
132             } else {
133                 prop = aTextName.substring(0, idx);
134                 newKey = aTextName.substring(idx + 1);
135             }
136 
137             if (prop != null) {
138                 Object obj = valueStack.findValue(prop);
139                 try {
140                     Object actionObj = ReflectionProviderFactory.getInstance().getRealTarget(prop, valueStack.getContext(), valueStack.getRoot());
141                     if (actionObj != null) {
142                         PropertyDescriptor propertyDescriptor = ReflectionProviderFactory.getInstance().getPropertyDescriptor(actionObj.getClass(), prop);
143 
144                         if (propertyDescriptor != null) {
145                             Class clazz = propertyDescriptor.getPropertyType();
146 
147                             if (clazz != null) {
148                                 if (obj != null )
149                                     valueStack.push(obj);
150                                 msg = findText(clazz, newKey, locale, null , args);
151                                 if (obj != null )
152                                     valueStack.pop();
153 
154                                 if (msg != null ) {
155                                     return msg;
156                                 }
157                             }
158                         }
159                     }
160                 } catch (Exception e) {
161                     LOG.debug("unable to find property " + prop, e);
162                 }
163             }
164         }
165 
166        查找 struts.custom.i18n.resources 常量指定 baseName 的系列资源文件。
167         GetDefaultMessageReturnArg result = null;
168         if (indexedTextName == null) {
169             result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage);
170         } else {
171             result = getDefaultMessage(aTextName, locale, valueStack, args, null );
172             if (result != null && result.message != null) {
173                 return result.message ;
174             }
175             result = getDefaultMessage(indexedTextName, locale, valueStack, args, defaultMessage);
176         }
177 
178         // could we find the text, if not log a warn
179         if (unableToFindTextForKey(result) && LOG.isDebugEnabled()) {
180             String warn = "Unable to find text for key ‘" + aTextName + "‘ " ;
181             if (indexedTextName != null) {
182                 warn += " or indexed key ‘" + indexedTextName + "‘ " ;
183             }
184             warn += "in class ‘" + aClass.getName() + "‘ and locale ‘" + locale + "‘";
185             LOG.debug(warn);
186         }
187 
188         return result != null ? result.message : null;
189     }

 

 

消息处理与国际化

标签:

原文地址:http://www.cnblogs.com/lflx/p/4398154.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!