Webwork做为经典的Web MVC 框架,个人觉得源码中配置文件这部分代码的实现十分考究。
支持自定义自己的配置文件、自定义配置文件读取类、自定义国际化支持。
可以作为参考,单独引入到其他项目中,下面是Configuration相关类的继承关系:
1. Configuration
- Configuration 作为 webwork 配置文件的核心类,起到了配置信息读取的门户,默认实现类中间引入了代理类 DelegatingConfiguration 与底层的具体实现读取的 PropertiesConfiguration 完全解耦。在项目中使用时,只需要引入 Configuration 类,如下代码即可获取配置信息;
Configuration.getString("webwork.locale")
- getString 方法会调用 Configuration 自身的get 方法,get 方法中调用 getConfiguration 方法:
1 public static String getString(String name) throws IllegalArgumentException { 2 String val = get(name).toString(); 3 return val; 4 }
1 public static Object get(String name) throws IllegalArgumentException { 2 Object val = getConfiguration().getImpl(name); 3 return val; 4 } 5 6 public static Configuration getConfiguration() { 7 return configurationImpl == null ? getDefaultConfiguration() : configurationImpl; 8 }
- Configuration 中定义的两个静态变量defaultImpl 和configurationImpl,还有 一个setConfiguration方法用来设置configurationImpl;
- defaultImpl 是 WebWork 的默认实现类实例的引用,在每一次读取配置文件时,都会去判断是否在 webwork.properties 是否配置了 webwork.configuration 参数(其实框架是无法实现热读配置文件的,下面会说到,每次判断只是确定读取配置信息,使用的框架默认类还是用户自定义类);
- 如果设置了在调用 getDefaultConfiguration() 获得自定义读取类引用 configurationImpl,否则返回 WebWork 自己的 Configuration 实现。
(这里要说一下,随意变动上线系统的配置文件,你会悲剧的,修改前记得问清楚)
1 private static Configuration getDefaultConfiguration() { 2 if (defaultImpl == null) { 3 defaultImpl = new DefaultConfiguration(); 4 try { 5 String className = getString("webwork.configuration"); 6 if (!className.equals(defaultImpl.getClass().getName())) { 7 try { 8 defaultImpl = (Configuration) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className)); 9 } catch (Exception e) { 10 log.error("Could not instantiate configuration", e); 11 } 12 } 13 return defaultImpl; 14 } catch (IllegalArgumentException localIllegalArgumentException) { 15 } 16 } 17 return defaultImpl; 18 }
- 第一次调用 getDefaultConfiguration() 方法时,默认实现 defaultImpl 是空,则进入创建一 个 WebWork 自己的实现 DefaultConfiguration 的实例,并通过这个实例读取 WebWork 配置信息。
- 上面代码第5行有个特殊的地方,和下面的 DelegatingConfiguration中的很相似,下面一起说。
2. DefaultConfiguration
1 public DefaultConfiguration() { 2 ArrayList list = new ArrayList(); 3 try { 4 list.add(new PropertiesConfiguration("webwork")); 5 } catch (Exception e) { 6 this.log.warn("Could not find webwork.properties"); 7 } 8 try { 9 list.add(new PropertiesConfiguration("com/opensymphony/webwork/default")); 10 } catch (Exception e) { 11 this.log.error("Could not find com/opensymphony/webwork/default.properties", e); 12 } 13 Configuration[] configList = new Configuration[list.size()]; 14 this.config = new DelegatingConfiguration((Configuration[]) list.toArray(configList)); 15 try { 16 StringTokenizer configFiles = new StringTokenizer((String) this.config.getImpl("webwork.custom.properties"), ","); 17 while (configFiles.hasMoreTokens()) { 18 String name = configFiles.nextToken(); 19 try { 20 list.add(new PropertiesConfiguration(name)); 21 } catch (Exception e) { 22 this.log.error("Could not find " + name + ".properties. Skipping"); 23 } 24 } 25 configList = new Configuration[list.size()]; 26 this.config = new DelegatingConfiguration((Configuration[]) list.toArray(configList)); 27 } catch (IllegalArgumentException localIllegalArgumentException) { 28 } 29 try { 30 StringTokenizer bundleFiles = new StringTokenizer((String) this.config.getImpl("webwork.custom.i18n.resources"), ","); 31 while (bundleFiles.hasMoreTokens()) { 32 String name = bundleFiles.nextToken(); 33 try { 34 this.log.info("Loading global messages from " + name); 35 LocalizedTextUtil.addDefaultResourceBundle(name); 36 } catch (Exception e) { 37 this.log.error("Could not find " + name + ".properties. Skipping"); 38 } 39 } 40 } catch (IllegalArgumentException localIllegalArgumentException1) { 41 } 42 }