Webwork 學習之路(四)Configuration 詳解,qt學習之路

來源:互聯網
上載者:User

Webwork 學習之路(四)Configuration 詳解,qt學習之路

  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 }DefaultConfiguration建構函式

 

  • DefaultConfiguration 並沒有直接取讀取properties檔案,而是通過 PropertiesConfiguration 來實現properties檔案的讀取;
  • PropertiesConfiguration 也同樣是 Configuration 的子類,通過java.util.Properties 來解析properties檔案,並 賦予自身Properties 執行個體settings,並覆蓋了父類的setImpl、getImpl、isSetImpl、 listImpl 四個方法;
  • DefaultConfiguration 通 過 PropertiesConfiguration 首 先 加 載 的 是 webwork.properties,之後又載入了default.properties;

   (這裡需要說一下,default.properties 是webwork 架構自身的設定檔,封裝在 jar 中,假如你在項目的 web.properties 中定義了與 default.properties 相同的參數,看上面程式設定檔的載入順序,架構先載入你的設定檔,然後載入預設設定檔,你會發現你的參數是不會起作用的,如果你想讓你的參數覆蓋架構中的,這裡你需要自訂設定檔,並且在 項目 webwork.properties 中配置 webwork.custom.properties 參數)

  • 將 PropertiesConfiguration 執行個體放入List中,然後建立一個和 List一樣大的Configuration[]數組,並把List 轉型為 Configuration[]賦予 執行個體化 DelegatingConfiguration
  • 載入完兩個properties 檔案,並建立了DelegatingConfiguration 執行個體之後, DefaultConfiguration開始在這兩個屬性檔案中尋找 webwork.custom.properties,檔案名稱之間用“,”隔開。找到配置後,分割檔案名稱並分別建立PropertiesConfiguration 執行個體,加入List,載入完所有配置文 件後重新建立DelegatingConfiguration 執行個體。
  • 載入完所有的WebWork 屬性檔案後, 尋找屬性檔案中指定的國際化資源檔(檔案名稱同樣用“,”隔開),如果有,則載入到 LocalizedTextUtil 中,供以後使用。

       (畢竟是好多年前編寫的源碼,這裡面的 StringTokenizer 出於相容性的原因已經被遺留(雖然在新代碼中並不鼓勵使用它)。API 中建議所有尋求此功能的人使用 String 的 split 方法或 java.util.regex 包)

3. DelegatingConfiguration
  • DelegatingConfiguration 也同樣是 Configuration 的子類,內部儲存了一個 Configuration[]數組configList,並覆 蓋了父類的setImpl、getImpl、isSetImpl、listImpl 四個方法,實現對configList 的操作;
  • 如果使用者沒有指定自己的 Configuration 實現,則 Configuration.getString 最終調用的是 DelegatingConfiguration 的 getImpl;
  • 在 DelegatingConfiguration 的setImpl 方法實現中,有一個特別的地方,其實也就是上面 Configuration提到的f,底層的實現:
 1     public void setImpl(String name, Object value) throws IllegalArgumentException, UnsupportedOperationException { 2         IllegalArgumentException e = null; 3         for (int i = 0; i < this.configList.length; i++) { 4             try { 5                 this.configList[i].getImpl(name); 6  7                 this.configList[i].setImpl(name, value); 8  9                 return;10             } catch (IllegalArgumentException ex) {11                 e = ex;12             }13         }14         throw e;15     }

   WebWork不支援動態增加屬性配置,但允許修改已配置的屬性, configList[i].getImpl(name); 調用的是 PropertiesConfiguration 的 getImpl 方法,實現如下:

1     public Object getImpl(String aName) throws IllegalArgumentException {2         Object setting = this.settings.get(aName);3         if (setting == null) {4             throw new IllegalArgumentException("No such setting:" + aName);5         }6         return setting;7     }

    PropertiesConfiguration 會在settings 裡去找name,如果找到就返回配置資訊,在 DelegatingConfiguration 的setImpl 方法中通過configList[i].setImpl(name, value)修改該屬性的配置,否則拋IllegalArgumentException 異常,該異常在 DelegatingConfiguration 的 getImpl 方法中截 獲 ,繼續往被調用函數拋。 此時則不會執行 configList[i].setImpl(name, value);從而保證了只有配置過了的屬性可以被修改,在服務啟動並執行過程中不會有新增的屬性,所有的屬性都由 Web 服務第一次啟動的時候載入。

4. webwork[三][四]小結

    以上分析我們可以看見,Web 服務啟動的時候,ServletDispatcher 通過 DefaultConfiguration 先 加 載 webwork.properties 和 default.properties , 並 查 找 webwork.properties中webwork.custom.properties 配置的其他屬性檔案載入。載入完畢 後再通過屬性中配置的 webwork.custom.i18n.resources 載入國際化資源檔供以後 使用。之後再尋找 webwork.configuration 屬性看是否使用者指定了自己的 Configuration 實現,如果有就用使用者自己的Configuration 實現,否則返回WebWork 自己的實現(DelegatingConfiguration)。大部分情況下,使用 WebWork 自己的實現 已經足夠,使用者不需要自己去實現一個 Configuration,除非你想載入XML等格式的配 置檔案。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.