請求寄件者與接收者解耦——命令模式(五)

來源:互聯網
上載者:User
6 請求日誌

       請求日誌就是將請求的記錄儲存下來,通常以記錄檔(Log File)的形式永久儲存在電腦中。很多系統都提供了記錄檔,例如Windows記錄檔、Oracle記錄檔等,記錄檔可以記錄使用者對系統的一些操作(例如對資料的更改)。請求記錄檔可以實現很多功能,常用功能如下:

       (1) “天有不測風雲”,一旦系統發生故障,記錄檔可以為系統提供一種恢複機制,在請求記錄檔中可以記錄使用者對系統的每一步操作,從而讓系統能夠順利恢複到某一個特定的狀態;

       (2) 請求日誌也可以用於實現批處理,在一個請求記錄檔中可以儲存一系列命令對象,例如一個命令隊列;

       (3) 可以將命令隊列中的所有命令對象都儲存在一個記錄檔中,每執行一個命令則從記錄檔中刪除一個對應的命令對象,防止因為斷電或者系統重啟等原因造成請求丟失,而且可以避免重新發送全部請求時造成某些命令的重複執行,只需讀取請求記錄檔,再繼續執行檔案中剩餘的命令即可。

       在實現請求日誌時,我們可以將命令對象通過序列化寫到記錄檔中,此時命令類必須實現java.io.Serializable介面。下面我們通過一個簡單一實例來說明記錄檔的用途以及如何?請求日誌:

       Sunny軟體公司開發了一個網站設定檔管理工具,可以通過一個可視化介面對網站設定檔進行增刪改等操作,該工具使用命令模式進行設計,結構如圖6所示:

圖6  網站設定檔管理工具結構圖

       現在Sunny軟體公司開發人員希望將對設定檔的操作請求記錄在記錄檔中,如果網站重新部署,只需要執行儲存在記錄檔中的命令對象即可修改設定檔。

       本執行個體完整代碼如下所示: [java] view plain copy import java.io.*;   import java.util.*;      //抽象命令類,由於需要將命令對象寫入檔案,因此它實現了Serializable介面   abstract class Command implements Serializable {       protected String name; //命令名稱       protected String args; //命令參數       protected ConfigOperator configOperator; //維持對接收者對象的引用              public Command(String name) {           this.name = name;       }              public String getName() {           return this.name;       }              public void setName(String name) {           this.name = name;       }              public void setConfigOperator(ConfigOperator configOperator) {           this.configOperator = configOperator;       }              //聲明兩個抽象的執行方法execute()       public abstract void execute(String args);       public abstract void execute();   }      //增加命令類:具體命令   class InsertCommand extends Command {       public InsertCommand(String name) {           super(name);       }              public void execute(String args) {           this.args = args;           configOperator.insert(args);       }              public void execute() {           configOperator.insert(this.args);       }   }      //修改命令類:具體命令   class ModifyCommand extends Command {       public ModifyCommand(String name) {           super(name);       }              public void execute(String args) {           this.args = args;           configOperator.modify(args);       }              public void execute() {           configOperator.modify(this.args);       }   }      //省略了刪除命令類DeleteCommand      //設定檔操作類:請求接收者。由於ConfigOperator類的對象是Command的成員對象,它也將隨Command對象一起寫入檔案,因此ConfigOperator也需要實現Serializable介面   class ConfigOperator implements Serializable {       public void insert(String args) {           System.out.println("增加新節點:" + args);       }              public void modify(String args) {           System.out.println("修改節點:" + args);       }              public void delete(String args) {           System.out.println("刪除節點:" + args);       }   }      //設定檔設定視窗類別:請求寄件者   class ConfigSettingWindow {       //定義一個集合來儲存每一次操作時的命令對象       private ArrayList<Command> commands = new ArrayList<Command>();       private Command command;           //注入具體命令對象       public void setCommand(Command command) {           this.command = command;       }              //執行設定檔修改命令,同時將命令對象添加到命令集合中       public void call(String args) {           command.execute(args);           commands.add(command);       }              //記錄請求日誌,組建記錄檔檔案,將命令集合寫入記錄檔       public void save() {           FileUtil.writeCommands(commands);       }              //從記錄檔中提取命令集合,並迴圈調用每一個命令對象的execute()方法來實現設定檔的重新設定       public void recover() {           ArrayList list;           list = FileUtil.readCommands();                      for (Object obj : list) {               ((Command)obj).execute();           }       }   }      //工具類:檔案操作類   class FileUtil {       //將命令集合寫入記錄檔       public static void writeCommands(ArrayList commands) {           try {               FileOutputStream file = new FileOutputStream("config.log");               //建立對象輸出資料流用於將對象寫入到檔案中               ObjectOutputStream objout = new ObjectOutputStream(new BufferedOutputStream(file));               //將對象寫入檔案               objout.writeObject(commands);               objout.close();               }           catch(Exception e) {                   System.out.println("命令儲存失敗。");                     e.printStackTrace();               }       }              //從記錄檔中提取命令集合       public static ArrayList readCommands() {           try {               FileInputStream file = new FileInputStream("config.log");               //建立對象輸入資料流用於從檔案中讀取對象               ObjectInputStream objin = new ObjectInputStream(new BufferedInputStream(file));                              //將檔案中的對象讀出並轉換為ArrayList類型               ArrayList commands = (ArrayList)objin.readObject();               objin.close();               return commands;               }           catch(Exception e) {                   System.out.println("命令讀取失敗。");                   e.printStackTrace();                   return null;                   }              }   }  

       編寫如下用戶端測試代碼: [java] view plain copy class Client {       public static void main(String args[]) {           ConfigSettingWindow csw = new ConfigSettingWindow(); //定義請求寄件者           Command command; //定義命令對象           ConfigOperator co = new ConfigOperator(); //定義請求接收者                      //四次對設定檔的更改           command = new InsertCommand("增加");           command.setConfigOperator(co);           csw.setCommand(command);           csw.call("網站首頁");                      command = new InsertCommand("增加");           command.setConfigOperator(co);           csw.setCommand(command);           csw.call("連接埠號碼");                      command = new ModifyCommand("修改");           command.setConfigOperator(co);           csw.setCommand(command);           csw.call("網站首頁");                      command = new ModifyCommand("修改");           command.setConfigOperator(co);           csw.setCommand(command);                   csw.call("連接埠號碼");                      System.out.println("----------------------------");           System.out.println("儲存配置");           csw.save();                          System.out.println("----------------------------");            System.out.println("恢複配置");           System.out.println("----------------------------");            csw.recover();         }   }  

       編譯並運行程式,輸出結果如下:

增加新節點:網站首頁

增加新節點:連接埠號碼

修改節點:網站首頁

修改節點:連接埠號碼

----------------------------

儲存配置

----------------------------

恢複配置

----------------------------

增加新節點:網站首頁

增加新節點:連接埠號碼

修改節點:網站首頁

修改節點:連接埠號碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.