http://blog.csdn.net/ly0814/archive/2005/07/22/431985.aspx
我們現在開(kāi)發(fā)的系統很多東西是定制的,比如表單、流程等,這樣系統的遷移出現了問(wèn)題,比如在公司為用戶(hù)定制了一些功能,拿到用戶(hù)那去的時(shí)候,就需要將定制的數據也拷貝過(guò)去,由于定制的信息比較雜,既有數據庫表記錄,也有文件,致使遷移數據經(jīng)常發(fā)生問(wèn)題,不是丟數據了,就是數據重復,導致定制的功能運行不起來(lái)。
所以我就考慮為系統做一個(gè)針對定制的數據能夠導入導出的程序,我想我們要操作的數據主要有兩類(lèi),物理表記錄和文件,其實(shí)很多系統的數據都是這些東西,所以我就想開(kāi)發(fā)的這套程序不要僅能完成現在的需求,應該是靈活的、可擴展的,可以針對這一類(lèi)的需求都能完成。
經(jīng)過(guò)仔細考慮和尋找可用的資源,我終于把這套程序作出來(lái)了,其中表數據操作我使用的是dbunit,感覺(jué)比較好用,而且支持很多數據庫,其實(shí)dbunit不是干這個(gè)用的,使用來(lái)測試數據庫程序操作的,不過(guò)干這個(gè)用更爽。
現在導入導出我們系統的定制數據已經(jīng)沒(méi)有問(wèn)題了,對于其他一些簡(jiǎn)單的表數據或文件備份也沒(méi)有問(wèn)題,如果將來(lái)出現更復雜的需求,或出現新的備份對象,我覺(jué)也應該可以擴展完成。
下面我說(shuō)一下我的實(shí)現思路。
這套程序目前支持兩大類(lèi)備份源:數據庫的表記錄、文件,文件又分為Properties文件和xml文件。
考慮實(shí)現思路是,將需要備份或恢復的數據源按指定的格式列成一個(gè)“清單“(定義清單格式),程序解析清單(backuplistparser), 解析的過(guò)程就是將需要備份的內容細化成無(wú)數的備份源(backupsource),形成集合,在解析過(guò)程中有可能調用每個(gè)備份源的過(guò)濾器(filter)或者備份源之間的關(guān)聯(lián)公式(Relationship)。
解析完成后,對所有的備份源進(jìn)行循環(huán),每個(gè)備份源將自己傳給相應的備份工作者(bakcupworker),通過(guò)回調工作者的backup()方法完成備份, 恢復也是一樣,調用工作者的import()方法完成。
下面我對程序清單和主要的類(lèi)簡(jiǎn)要說(shuō)明一下:

備份清單
程序清單是一個(gè)xml文件,包含兩方面的信息,一是環(huán)境參數,比如數據庫連接信息、需要備份的數據路徑的等;二就是需要備份源的列表,每一個(gè)備份源又包含自己的描述信息、過(guò)濾條件,和別的備份源的關(guān)聯(lián)條件。
下面是一個(gè)例子:
<?xml version="1.0" encoding="gb2312"?>
<backuplist>
//環(huán)境信息
<context>
//系統文件的路徑,
比如C:\WebSphere\AppServer\installedApps\lc-ecp\v3log.ear\v3log.war\eaiPath
<sysfileroot>I:/eaipath</sysfileroot>
//存放導出數據的路徑
<backupfileroot>c:/temp</backupfileroot>
//數據庫連接信息,目前只支持db2,用的是jcc連接
<servername>lc-ecp</servername>
<databasename>v3ecpdb</databasename>
<user>db2admin</user>
<password>ourecp</password>
</context>
//備份源列表
//數據庫表processtype
<backupsource id="processtype" type="table" tablename="WFPROCESSTYPE">
//過(guò)濾器,值用‘,’分割,僅備份字段id值等于P1119505745079或P1115713181485
//可以不設置過(guò)濾器
<filter>
<property name="ID" value="P1119505745079,P1115713181485"/>
</filter>
//關(guān)聯(lián)的備份源
<relationships>
//關(guān)聯(lián)的備份源wfproperty
<relationship id="wfproperty">
<relation>one-to-many</relation>
//關(guān)聯(lián)的條件是表processtype字段id的值和wfproperty的字段objid的值相等
<relationdefine><![CDATA[ID=OBJID]]></relationdefine>
</relationship>
//關(guān)聯(lián)的備份源wflocaloperate,是文件備份源
<relationship id="wflocaloperate">
<relation>one-to-one</relation>
//關(guān)聯(lián)的條件是wflocaloperate備份源的文件名包含表processtype字段id值
<relationdefine><![CDATA[ID=include]]></relationdefine>
</relationship>
//關(guān)聯(lián)的備份源wflocaloperate,是xml文件備份源
<relationship id="process">
<relation>one-to-meny</relation>
//關(guān)聯(lián)的條件是wflocaloperate備份源的xml文件的process節點(diǎn)的參數type的值等于表processtype字段id值
<relationdefine filterclass=""><![CDATA[ID=nodeattr:process.type]]></relationdefine>
</relationship>
</relationships>
</backupsource>
<backupsource id="wfproperty" type="table" tablename="WFPROPERTY">
</backupsource>
<backupsource id="wflocaloperate" type="file" path="/wflocaloperate/" filename="">
</backupsource>
<backupsource id="process" type="xmlfile" path="/wf/process/" filename="">
<relationships>
<relationship id="wffield">
<relation>one-to-one</relation>
<relationdefine><![CDATA[nodeattr:process.id=nodeattr:process.id]]></relationdefine>
</relationship>
</relationships>
</backupsource>
</backuplist>
SysBackupExport
數據導出入口程序,傳入清單文件,調用BackupListXmlParse進(jìn)行解析,形成備份源的集合,然后根據導出方式請求,進(jìn)行數據導出。
有五種到處方式:
Ø exportAll,全部數據導出,循環(huán)導出清單所有備份源,會(huì )執行每一個(gè)備份源filter,如果有的話(huà)
Ø exportAllIgnoreFilter,循環(huán)導出清單所有備份源,忽略filter,真正的全部導出
Ø ExportById 根據id導出某一備份源,會(huì )執行此備份源的filter,并且導出其關(guān)聯(lián)備份源
Ø ExportByIdIgnoreFilter 根據id導出某一備份源,忽略此備份源的filter,并且導出其關(guān)聯(lián)備份源
Ø ExportByIdIgnoreRelation 僅根據id導出某一備份源,會(huì )執行此備份源的filter,不導出關(guān)聯(lián)備份源
Ø ExportByIdIgnoreFilterAndRelation僅根據id導出某一備份源,忽略此備份源的filter,不導出關(guān)聯(lián)備份源
SysBackupImport
數據導入入口程序,傳入清單文件調用BackupListXmlParse進(jìn)行解析,形成備份源的集合,循環(huán)備份源導入,如果數據表記錄重復,將會(huì )更新,如果文件重復,將會(huì )覆蓋
BackupListXmlParse
解析備份清單,設置環(huán)境參數,循環(huán)設置每一個(gè)備份源,設置備份源的filter和Relationship,形成備份源的集合
backupsource
備份源對象,這里定義了一接口.
public interface BackupSource {
public void export(); //數據備份,導出,由BackupWorker完成
public void bImport(); //數據導入,由BackupWorker完成
public Map associate(Map sources, Map targetSources); //執行關(guān)聯(lián)定義,獲取自己相關(guān)聯(lián)的備份源
public void filter();//執行過(guò)濾,由filter完成
public String getId();
public String getType();
public void setId(String string);
public Filter getFilter();
public void setFilter(Filter f);
public Filter createDefaultFilter();
public BackupWorker createDefaultWorker();
public List getRelationships();
public void setRelationships(List list);
}
目前實(shí)現有四個(gè):
TableBackupSource 數據庫物理表
FileBackupSource 普通文件
PropertiesBackupSource Properties文件
XmlfileBackupSource xml文件
Filter
過(guò)濾器,核心方法就是filter()方法,說(shuō)白了就是為物理表備份源產(chǎn)生where條件,為文件備份源過(guò)濾那些文件允許備份。
定義了一個(gè)抽象類(lèi),有四個(gè)實(shí)現,分別針對不同的數據備份源:
DBTableQueryFilter
DefaultFileFilter
PropertiesFileFilter
XmlFileFilter
BackupWorker
完成真正的導入導出工作,定義了一個(gè)接口,核心方法就是兩個(gè)export()和bimport(),
目前有三個(gè)實(shí)現。
DBQueryBackupWorker
DefaultFileBackupWorker
PropertiesBackupWorker
對于數據庫表記錄的存取,我沒(méi)有自己寫(xiě),感覺(jué)太復雜,我用的是開(kāi)源項目DBUNIT,借用了它可以把表記錄生成XML文件,并且還可以把XML文件再插回到物理表的功能.
對于文件的存取,自己寫(xiě)的,無(wú)非就是用流的寫(xiě)入寫(xiě)出罷了。就不細說(shuō)了。
總體感覺(jué),這套程序不大,基本實(shí)現了最初的想法,總共也就是十幾個(gè)類(lèi),主要的收獲就是按面向對象的思想來(lái)進(jìn)行設計的,鍛煉了一回(當然這樣設計可能不是最好的,自我感覺(jué)盡力思考了,以后有更好的想法再改進(jìn))。
不足的地方,備份源之間的關(guān)聯(lián)公式定義,感覺(jué)比較幼稚,而且不好擴充,暫時(shí)又想不出更好的方式;導入導出的數據最好能打一個(gè)包;目前只能支持db2數據庫。
目前功能不是很強,應用范圍比較窄,感覺(jué)應該還可以擴充,或者干點(diǎn)別的任務(wù),比如用定時(shí)器定時(shí)備份系統的全部數據什么的,暫時(shí)就這樣吧。
聯(lián)系客服