Vincent

          Vicent's blog
          隨筆 - 74, 文章 - 0, 評論 - 5, 引用 - 0
          數據加載中……

          Apache Commons Chain簡明手冊

          基本對象

          1. ? Command 接口。它是 Commons Chain 中最重要的接口,表示在 Chain 中的具體某一步要執行的命令。它只有一個方法: boolean execute(Context context) 。如果返回 true ,那么表示 Chain 的處理結束, Chain 中的其他命令不會被調用;返回 false ,則 Chain 會繼續調用下一個 Command ,直到:

          - ????????? Command 返回 true

          - ????????? Command 拋出異常;

          - ????????? Chain 的末尾;

          2. ? Context 接口。它表示命令執行的上下文,在命令間實現共享信息的傳遞。 Context 接口的父接口是 Map ContextBase 實現了 Context 。對于 web 環境,可以使用 WebContext 類及其子類( FacesWebContext PortletWebContext ServletWebContext )。

          3. ? Chain 接口。它表示“命令鏈”,要在其中執行的命令,需要先添加到 Chain 中。 Chain 的父接口是 Command ChainBase 實現了它。

          4. ? Filter 接口。它的父接口是 Command ,它是一種特殊的 Command 。除了 Command execute ,它還包括一個方法: boolean postprocess(Context context, Exception exception) Commons Chain 會在執行了 Filter execute 方法之后,執行 postprocess (不論 Chain 以何種方式結束)。 Filter 的執行 execute 的順序與 Filter 出現在 Chain 中出現的位置一致,但是執行 postprocess 順序與之相反。如:如果連續定義了 filter1 filter2 ,那么 execute 的執行順序是: filter1 -> filter2 ;而 postprocess 的執行順序是: filter2 -> filter1

          5. ? Catalog 接口。它是邏輯命名的 Chain Command 集合。通過使用它, Command 的調用者不需要了解具體實現 Command 的類名,只需要通過名字就可以獲取所需要的 Command 實例。

          基本使用

          1. ???????? 執行由順序的命令組成的流程,假設這條流程包含 1 2 3 步。

          t ??????? 實現要執行的命令步驟:

          public class Command1 implements Command {

          ??? public boolean execute(Context arg0) throws Exception {

          ??????? System.out.println("Command1 is done!");

          ??????? return false;

          ??? }

          }

          public class Command2 implements Command {

          ??? public boolean execute(Context arg0) throws Exception {

          ??????? System.out.println("Command2 is done!");????

          ??????? return false;

          ??? }

          }

          public class Command3 implements Command {

          ??? public boolean execute(Context arg0) throws Exception {

          ??????? System.out.println("Command3 is done!");

          ??????? return true;

          ??? }

          }

          ?

          t ??????? 注冊命令,創建執行的 Chain

          public class CommandChain extends ChainBase {

          ??? // 增加命令的順序也決定了執行命令的順序

          ??? public CommandChain(){

          ??????? addCommand( new Command1());

          ??????? addCommand( new Command2());

          ??????? addCommand( new Command3());

          ??? }

          ???

          ??? public static void main(String[] args) throws Exception{

          ??????? Command process = new CommandChain();

          ??????? Context ctx= new ContextBase();

          ??????? process.execute( ctx);

          ??? }

          }

          ?

          2. ???????? 使用配置文件加載 Command 。除了在程序中注冊命令之外,還可以使用配置文件來完成。

          t ??????? 對于例 1 ,配置文件可以寫成:

          <?xml version="1.0" encoding="gb2312"?>

          <catalog>

          ?????? <chain name="CommandChain">

          ??????? <!-- 定義的順序決定執行的順序 -->

          ????????????? <command id="command1" className= "chain.Command1"/>

          ????????????? <command id="command2" className= "chain.Command2"/>

          ????????????? <command id="command3" className= "chain.Command3"/>

          ?????? </chain>

          ? ?? <command name="command4" className="chain.Command1"/>

          </catalog>

          t ??????? 裝入配置文件的代碼如下:

          public class CatalogLoader {

          ??? static final String cfgFile= "/chain/chain-cfg.xml";???

          ??? public static void main(String[] args) throws Exception{

          ??????? CatalogLoader loader= new CatalogLoader();

          ??????? ConfigParser parser= new ConfigParser();

          ???????

          ??????? parser.parse( loader.getClass().getResource( cfgFile));

          ??????? Catalog catalog= CatalogFactoryBase.getInstance().getCatalog();

          ??????? // 加載 Chain

          ??????? Command cmd= catalog.getCommand("CommandChain");

          ??????? Context ctx= new ContextBase();

          ??????? cmd.execute( ctx);

          // 加載 Command

          cmd= catalog.getCommand( "command4");

          ??????? cmd.execute( ctx);

          ??? }

          }

          注意:使用配置文件的話,需要使用 Commons Digester 。而 Digester 則依賴: Commons? Collections Commons Logging Commons BeanUtils

          3. ???????? 加載 Catalog web 應用。為了在 web 應用中加載 Catalog ,需要在對應的 web.xml 中添加:

          <context-param>

          ? <param-name>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</param-name>

          ? <param-value>resources/catalog.xml</param-value>

          </context-param>

          <listener>

          ? <listener-class>org.apache.commons.chain.web.ChainListener</listener-class>

          </listener>

          缺省情況下, Catalog 會被加載到 Servlet Context 中,對應的屬性名字是“ catalog ”。因此獲取 Catalog

          Catalog catalog = (Catalog) request.getSession()

          ??????? ????????????????????.getServletContext().getAttribute("catalog");

          4. ???????? Filter 的使用。 Filter 是一種特殊的 Command ,它除了 execute 方法會被執行之外,同時還會在 Chain 執行完畢之后(不論是正常結束還是異常結束)執行 postprocess 。因此,可以將它和 Servlet 中的 Filter 做類比: execute 相當于處理前操作(相對下一個 Command 來說), postprocess 相當于處理后操作。 Filter 的使用以及配置和 Command 完全一樣,為了在 Command1 之前添加一個 Filter

          t ??????? 定義 Filter

          public class Filter1 implements Filter {

          ??? public boolean postprocess(Context arg0, Exception arg1) {

          ??????? System.out.println("Filter1 is after done!");

          ??????? return false;

          ??? }

          ??? public boolean execute(Context arg0) throws Exception {

          ?? ?????System.out.println("Filter1 is done!");

          ??????? return false;

          ??? }

          }

          ?

          t ??????? 修改配置文件,在上述的配置文件中的 command1 之前添加:

          <command id="filter1" className= "chain.Filter1"/>

          ?????? Filter 的還有一個常用的用法:對于異常的過濾。當 Command 拋出異常時,最終中會返回到最開始的調用處。有時期望不拋出這些異常,而在內部消化掉,那么就可以利用 Filter 。因為 Commons Chain 確保會調用已經執行了 execute 方法的 Filter postprocess 方法,即使在出現異常時也是如此。因此,對應的 postprocess 方法可以寫為:

          ?????? public boolean postprocess(Context arg0, Exception arg1) {

          ??????? // 返回 true ,表示非空異常已被處理,無需再拋出。

          ??????? // 否則,異常會被拋出

          ??????? if( null!= arg1) return true;

          ??????? else return false;

          ??? }

          5. ???????? 對于復雜的 Chain ,可能需要使用內嵌的 Chain ,內嵌 Chain 可以類比一個子過程。此時,可以使用 LookupCommand 。以例 1 為例,假設其中的 command2 需要擴展成為一個子過程,那么配置文件修改如下:

          <?xml version="1.0" encoding="UTF-8"?>

          <catalog>

          ?????? <chain name="CommandChain">

          ????????????? <command id="command1" className= "chain.Command1"/>

          ????????????? <command id="filter1" className= "chain.Filter1"/>

          ????????????? <command

          className="org.apache.commons.chain.generic.LookupCommand"

          ???????????????????? name="chain_command3"

          ???????????????????? optional="true"/>

          ????????????? <command id="command2" className= "chain.Command2"/>

          ?????? </chain>

          ?????? <chain name="chain_command3">

          ????????????? <command id="command3" className= "chain.Command3"/>

          ?????? </chain>

          </catalog>

          其中, optional 如果設為 true ,那么如果沒有找到對應的類時,程序不會拋出異常。此時,仿佛命令不存在一樣。如果為 false ,那么在找不到對應的類時,會拋出異常。

          6. ???????? <define> 的使用。配置文件的引入,使得 Commons Chain 的靈活性大大的提高。在實際的使用過程中,存在著同一個 Command 被多個 Chain 使用的情形。如果每次都書寫 Command 的類名,尤其是前面的包名特別長的情況下,是非常枯燥的。而 <define> 的作用就是為了解決這樣的麻煩。通過定義 Command Chain 的別名,來簡化書寫。例 5 的配置文件,可以書寫成:

          <?xml version="1.0" encoding="gb2312"?>

          <catalog>

          ??? <!-- Command 的別名,以后直接使用即可 -->

          ?????? <define name="command1" className="chain.Command1"/>

          ?????? <define name="command2" className="chain.Command2"/>

          ?????? <define name="command3" className="chain.Command3"/>

          ?????? <define name="filter1" className="chain.Filter1"/>

          ?????? <define name="lookupCommand"

          ????????????? ??? className="org.apache.commons.chain.generic.LookupCommand"/>

          ??????

          ?????? <chain name="CommandChain">

          ????????????? <command1 id="1"/>

          ????????????? <filter1 id="2"/>

          ????????????? <lookupCommand name="chain_command3" optional="true"/>

          ????????????? <command2 id="3"/>

          ?????? </chain>

          ??????

          ?????? <chain name="chain_command3">

          ????????????? <command3 id="3"/>

          ?????? </chain>

          ??????

          ?????? <command1 name="command4"/>

          </catalog>

          ?

          總結

          ?????? Commons Chain 實現了 Chain of Responsebility Command 模式,其中的 Catalog + 配置文件的方式使得調用方和 Command 的實現方的耦合度大大的降低,提高了靈活性。對于配置文件,通常可以:

          - ????????? 作為 Command 的索引表,需要時按名字索引創建實例。

          - ????????? 利用 Chain 以及內嵌 Chain ,完成一組連續任務和 Command 的復用,引入 Filter 可以獲得與 Servlet Filter 一樣的好處。

          - ????????? 使用 <define> 定義別名,簡化書寫。

          posted on 2006-08-22 10:47 Binary 閱讀(2156) 評論(0)  編輯  收藏 所屬分類: Apache jakarta

          主站蜘蛛池模板: 大安市| 江永县| 黑水县| 平度市| 伊吾县| 霍山县| 舒兰市| 福建省| 清河县| 锡林郭勒盟| 太白县| 四川省| 利川市| 无棣县| 沁源县| 周口市| 鄂托克旗| 施秉县| 桐乡市| 冷水江市| 集贤县| 周口市| 英超| 临西县| 三明市| 崇左市| 静海县| 鄂伦春自治旗| 盐城市| 韶山市| 婺源县| 巢湖市| 韶关市| 汕头市| 屯昌县| 宜黄县| 镇宁| 开江县| 武夷山市| 建宁县| 东乡族自治县|