<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網(wǎng) 大學(xué)生計(jì)算機(jī)學(xué)習(xí)社區(qū)

    CowNew開(kāi)源團(tuán)隊(duì)

    http://www.cownew.com 郵件請(qǐng)聯(lián)系 about521 at 163.com

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評(píng)論 :: 0 Trackbacks

    #

    JDBMonitor是一個(gè)開(kāi)源項(xiàng)目。使用它開(kāi)發(fā)者可以很輕松為系統(tǒng)增加數(shù)據(jù)庫(kù)執(zhí)行日志功能。它使用十分方便,您所需要做的唯一事情就是在您系統(tǒng)的JDBC連接字符串前增加類(lèi)似于 "listenerconfig=/config.xml:url=" 的字符即可,不用寫(xiě)任何代碼。

    使用 JDBMonitor,您可以把數(shù)據(jù)庫(kù)執(zhí)行情況記錄通過(guò)各種方式記錄下來(lái),比如打印到控制臺(tái)、輸出到文件或者通過(guò)socket傳送給遠(yuǎn)程客戶端。JDBMonitor是可擴(kuò)展的,您可以擴(kuò)展它來(lái)將執(zhí)行情況通過(guò)其他方式記錄下來(lái),您所需要做的就是寫(xiě)一個(gè)實(shí)現(xiàn)IDBListener接口的類(lèi)即可。

    JDBMonitor遵守 GNU Lesser General Public Licence (LGPL)協(xié)議。此協(xié)議包含在發(fā)行包中。

    入門(mén)

    幾乎所有大型數(shù)據(jù)庫(kù)應(yīng)用都包含有自己的SQL執(zhí)行日志功能,此功能不僅能幫助開(kāi)發(fā)人員調(diào)試,而且可以為DBA(數(shù)據(jù)庫(kù)管理員)提供系統(tǒng)的運(yùn)行信息。

    (1)很難將業(yè)務(wù)邏輯同日志代碼分離

    (2)降低了代碼的可讀性。

    (3)降低了系統(tǒng)的運(yùn)行速度。在記錄日志的時(shí)候,程序會(huì)暫停運(yùn)行等待直到記錄完成,而I/O操作是相當(dāng)耗時(shí)的。

    (4)很難記錄運(yùn)行耗時(shí)、語(yǔ)句參數(shù)等其他信息

    (5)很難為我們無(wú)法修改代碼的系統(tǒng)(例如沒(méi)有源代碼的系統(tǒng))或者很難增加記錄日志功能代碼的系統(tǒng)(比如系統(tǒng)使用了ORMapping)增加日志功能。

    JDBMonitor 則不同:

    (1)您最多只需要修改一行代碼。您需要修改的代碼就是這一行:Class.forName("com.cownew.JDBMonitor.jdbc.DBDriver") ,然后再修改一下 JDBC連接字符串,只要從 “jdbc:db2://10.74.198.247:50000/app”修改成” listenerconfig=config.xml:url= jdbc:db2://10.74.198.247:50000/app”就可以了。在您使用WebLogic ,Tomcat或其他服務(wù)器的數(shù)據(jù)源功能的時(shí)候,連修改代碼這一步都是無(wú)需的。

    (2)JDBMonitor另起一個(gè)線程來(lái)記錄SQL,所以它不會(huì)對(duì)程序運(yùn)行速度有任何影響。

    (3)它是高度可擴(kuò)展的,所以您可以擴(kuò)展它來(lái)把執(zhí)行情況通過(guò)其他方式記錄。比如,您可以寫(xiě)一個(gè)擴(kuò)展類(lèi),來(lái)通過(guò)電子郵件將日志發(fā)送出去。

    取得 JDBMonitor

    JDBMonitor的最新穩(wěn)定版本可以在JDBMonitor的網(wǎng)站上取得:

    http://www.cownew.com/JDBMonitor

    使用 JDBMonitor

    1 將 jdbmonitor.jar放到您系統(tǒng)的類(lèi)路徑下。

    2 讓系統(tǒng)加載 JDBMonitorJDBC驅(qū)動(dòng)。

    這一步將會(huì)依您系統(tǒng)加載JDBC驅(qū)動(dòng)的方式的不同而不同。

    (1)如果您通過(guò)代碼的形式加載JDBC驅(qū)動(dòng),例如:

    ?? Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver”);
    ?? Connection cn = DriverManager.getConnection(……);

    在這種情況下 ,您必須修改 “Class.forName”這一句來(lái)加載JDBMonitor的JDBC驅(qū)動(dòng)(“com.cownew.JDBMonitor.jdbc.DBDriver”),而非以前的數(shù)據(jù)庫(kù)JDBC驅(qū)動(dòng)。

    例如:

    Class.forName(“com.cownew.JDBMonitor.jdbc.DBDriver”);
    ?? Connection cn = DriverManager.getConnection(……);

    (2)如果您在配置文件中指定JDBC驅(qū)動(dòng),比如,數(shù)據(jù)源配置文件或者其他類(lèi)似的文件。

    請(qǐng)修改原來(lái)的??JDBC驅(qū)動(dòng)類(lèi)為 “com.cownew.JDBMonitor.jdbc.DBDriver” 。

    3 讓 JDBMonitor加載能夠加載原來(lái)的JDBC驅(qū)動(dòng)

    JDBMonitor的工作原理就是截獲JDBC驅(qū)動(dòng)的SQL語(yǔ)句調(diào)用、記錄SQL語(yǔ)句,然后將SQL語(yǔ)句重新轉(zhuǎn)發(fā)給原來(lái)的JDBC驅(qū)動(dòng),所以JDBMonitor必須首先向DriverManager注冊(cè)JDBC驅(qū)動(dòng)。

    原來(lái)的JDBC驅(qū)動(dòng)定義在配置文件的“JdbcDrivers” 段中。
    <JdbcDrivers>
    ??? <JdbcDriver class=" com.mysql.jdbc.Driver"/>
    ? </JdbcDrivers>

    4 在原來(lái)的JDBC連接字符串前增加 JDBMonitor所需的信息。

    您所需要做的就是將” listenerconfig=<configfilepath>:url=” 增加到原來(lái)的JDBC連接字符串前。“<configfilepath>”代表配置文件的路徑,下面集中路徑都是合法的:

    /com/jdbmonitor/config.xml
    com/jdbmonitor/config.xml
    c:/ jdbmonitor /config.xml

    JDBMoinitor使用getClass().getResourceAsStream加載類(lèi)似于“/com/jdbmonitor/config.xml” and “com/jdbmonitor/config.xml” 的類(lèi)路徑文件,使用 FileInputStream加載類(lèi)似于 “c:/ jdbmonitor /config.xml”的配置文件。

    5 指定您要使用監(jiān)聽(tīng)器:

    您可以把數(shù)據(jù)庫(kù)執(zhí)行情況記錄通過(guò)各種方式記錄下來(lái),比如打印到控制臺(tái)、輸出到文件或者通過(guò)socket傳送給遠(yuǎn)程客戶端。

    我們已經(jīng)開(kāi)發(fā)了如下常用的監(jiān)聽(tīng)器:FileDBListener、ConsoleDBListener、 SocketDBListene、DataBaseDBListener。當(dāng)然您也可以開(kāi)發(fā)滿足您要求的監(jiān)聽(tīng)器。
    監(jiān)聽(tīng)器定義在配置文件的 “Listeners”段中:

    <Listeners>
    ??? <!--ConsoleDBListener no arguments-->
    ??? <Listener class="com.cownew.JDBMonitor.listenerImpl.ConsoleDBListener" arg=""/>
    ???
    ??? <!--the arguments of FileDBListener is the file to log the SQL statement -->
    ??? <Listener class="com.cownew.JDBMonitor.listenerImpl.FileDBListener" arg="c:/aaa.txt"/>
    ???
    ??? <!--the arguments of SocketDBListener is the bound socket port of the listener server -->
    ??? <Listener class="com.cownew.JDBMonitor.listenerImpl.SocketDBListener" arg="9527"/>
    ? </Listeners>

    搞定!啟動(dòng)您的系統(tǒng)。耶!SQL語(yǔ)句被記錄下來(lái)了,我們可以在控制臺(tái)、文件甚至遠(yuǎn)程監(jiān)視器中看到日志了。

    舉例

    mvnforum的例子:

    您可以從http://www.mvnForum.com得到mvnforum。我演示用的版本是1.0。

    (1)打開(kāi)webapp\WEB-INF\classes\ mvncore.xml,重新配置:

    修改之前:

    <driver_class_name>com.mysql.jdbc.Driver</driver_class_name>
    <database_url>listenerconfig=c:/log/jdbmonitor/config.xml:url= jdbc:mysql://localhost/mvnforum?useUnicode=true&amp;characterEncoding=utf-8</database_url>

    修改之后:
    <driver_class_name> com.cownew.JDBMonitor.jdbc.DBDriver </driver_class_name>
    ??????? <database_url>jdbc:mysql://localhost/mvnforum?useUnicode=true&amp;characterEncoding=utf-8</database_url>

    (2)創(chuàng)建文件 c:/log/jdbmonitor/config.xml。我只想將SQL語(yǔ)句記錄到文本文件中,所以我做如下配置:
    <config>
    ? <Listeners>
    ??? <!--the arguments of FileDBListener is the file to log the SQL statement -->
    ??? <Listener class="com.cownew.JDBMonitor.listenerImpl.FileDBListener" arg="c:/log.txt"/>
    ? </Listeners>
    ? <JdbcDrivers>
    ??? <JdbcDriver class="com.mysql.jdbc.Driver"/>
    ? </JdbcDrivers>
    </config>
    (3) 將 jdbmonitor.jar放到webapp\WEB-INF\lib下。
    (4) 搞定!

    Jive的例子:

    您可以從http://www.jivesoftware.com得到Jive。我演示用的版本是 Jive 2.0 beta版。

    (1)打開(kāi)http://localhost:8080/jive/admin/

    “jdbc” 填為:com.cownew.JDBMonitor.jdbc.DBDriver

    “server” 填為:c:/log/jdbmonitor/config.xml:url=jdbc:mysql://locahost/jive
    (2)jdbmonitor.jar放到WEB-INF\lib下
    (4) 象mvnforum中一樣創(chuàng)建同樣的 c:/log/jdbmonitor/config.xml 文件.
    (4) 搞定!

    代碼方式的例子:

    盡管直接在代碼中指定系統(tǒng)所用的JDBC驅(qū)動(dòng)類(lèi)名和JDBC連接字符串是不推薦的,但是仍然有系統(tǒng)是這么做的。

    比如:

    ????????????? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    ????????????? Connection conn = null;
    ????????????? PreparedStatement ps = null;
    ????????????? try
    ????????????? {
    ???????????????????? conn = DriverManager
    ?????????????????????????????????? .getConnection("jdbc:odbc:MQIS");
    ???????????????????? for (int i = 0; i < 1000; i++)
    ???????????????????? {???????????????????
    ??????????????????????????? ps = conn.prepareStatement("update T_Material set fid=fid");
    ??????????????????????????? ps.execute();
    ??????????????????????????? ps.close();
    ???????????????????? }
    ????????????? } finally
    ????????????? {
    ???????????????????? ....?????????
    ????????????? }

    (1)修改一下代碼為:
    ?????????????? Class.forName("com.cownew.JDBMonitor.jdbc.DBDriver");
    ????????????? Connection conn = null;
    ????????????? PreparedStatement ps = null;
    ????????????? try
    ????????????? {
    ???????????????????? conn = DriverManager.getConnection("listenerconfig= c:/log/jdbmonitor/config.xml:url=jdbc:odbc:MQIS");
    ???????????????????? for (int i = 0; i < 1000; i++)
    ???????????????????? {
    ??????????????????????????? ps = conn.prepareStatement("update T_Material set fid=fid");
    ??????????????????????????? ps.execute();
    ??????????????????????????? ps.close();
    ???????????????????? }
    ????????????? } finally
    ????????????? {
    ????????????? ?????? ....?????????
    ????????????? }

    (2)創(chuàng)建c:/log/jdbmonitor/config.xml文件。我想記錄SQL語(yǔ)句到文本文件中同時(shí)輸出到控制臺(tái),這樣可以輔助我進(jìn)行調(diào)試,所以我配置如下:
    <config>
    ? <Listeners>
    ??? <!--the arguments of FileDBListener is the file to log the SQL statement -->
    <Listener class="com.cownew.JDBMonitor.listenerImpl.FileDBListener" arg="c:/log.txt"/>

    <!--ConsoleDBListener no arguments-->
    <Listener class="com.cownew.JDBMonitor.listenerImpl.ConsoleDBListener" arg=""/>
    ? </Listeners>
    ? <JdbcDrivers>
    ??? <JdbcDriver class="com.mysql.jdbc.Driver"/>
    ? </JdbcDrivers>
    </config>
    (3) 將 jdbmonitor.jar放到類(lèi)路徑下。
    (4) 搞定!

    監(jiān)聽(tīng)器

    我們已經(jīng)開(kāi)發(fā)了如下常用的監(jiān)聽(tīng)器:FileDBListener、ConsoleDBListener、 SocketDBListener、DataBaseDBListener。

    1、ConsoleDBListener 控制臺(tái)監(jiān)聽(tīng)器

    ConsoleDBListener會(huì)將SQL語(yǔ)句打印到控制臺(tái)中。

    這個(gè)監(jiān)聽(tīng)器很容易配置:

    <Listener class="com.cownew.JDBMonitor.listenerImpl.ConsoleDBListener" arg=""/>

    2、FileDBListener 文件監(jiān)聽(tīng)器

    FileDBListener 會(huì)將SQL語(yǔ)句保存到文本文件中。

    如下配置:

    <Listener class="com.cownew.JDBMonitor.listenerImpl.FileDBListener" arg="c:/aaa.txt"/>

    arg="c:/aaa.txt"表示日志將保存到文件c:/aaa.txt中。

    3、SocketDBListener Socket監(jiān)聽(tīng)器

    SocketDBListener是一個(gè)socket服務(wù)器,客戶端連接到它上邊以后就可以接收到它發(fā)出的SQL語(yǔ)句。

    如下配置:

    <Listener class="com.cownew.JDBMonitor.listenerImpl.SocketDBListener" arg="9527"/>

    arg="9527"表示服務(wù)器將在9527端口監(jiān)聽(tīng)。

    我們已經(jīng)開(kāi)發(fā)了如下兩種客戶端:SocketConsoleClient(Socket控制臺(tái)客戶端) 和 SocketSwingClient(Socket Swing客戶端)。

    SocketConsoleClient工作在控制臺(tái)中:

    SocketSwingClient是一個(gè)Swing GUI客戶端:

    您可以運(yùn)行"java -classpath jdbmonitor.jar com.cownew.JDBMonitor.listenerImpl.sckListenerClient.SocketConsoleClient" 來(lái)啟動(dòng)SocketConsoleClient,運(yùn)行"java -classpath jdbmonitor.jar com.cownew.JDBMonitor.listenerImpl.sckListenerClient.SocketSwingClient"啟動(dòng)SocketSwingClient

    您可以編寫(xiě)符合您自己要求的客戶端,具體細(xì)節(jié)請(qǐng)參考com.cownew.JDBMonitor.listenerImpl.sckListenerClient.ListenerClientcom.cownew.JDBMonitor.listenerImpl.sckListenerClient.IDBSocketClientListener.

    4、DataBaseDBListener

    DataBaseDBListener將會(huì)把SQL語(yǔ)句記錄到數(shù)據(jù)庫(kù)中:

    如下配置:

    <Listener class="com.cownew.JDBMonitor.listenerImpl.DataBaseDBListener"
    arg="dburl=jdbc:odbc:MQIS;user=;password=;logtable=T_Log_SQLLog"/>

    "dburl=jdbc:odbc:MQIS;user=;password=;"表示目標(biāo)數(shù)據(jù)庫(kù)的JDBC連接字符串。"logtable=T_Log_SQLLog" 表示SQL記錄將被保存到哪個(gè)表中,默認(rèn)的是T_Log_SQLLog

    如果目標(biāo)數(shù)據(jù)庫(kù)用的JDBC驅(qū)動(dòng)與被監(jiān)控的數(shù)據(jù)庫(kù)不同,請(qǐng)將它加入配置文件的 "JdbcDrivers" 部分,例如:

    <config>
    <Active>true</Active>
    <Listeners>

    <Listener class="com.cownew.JDBMonitor.listenerImpl.ConsoleDBListener" arg=""/>

    <Listener class="com.cownew.JDBMonitor.listenerImpl.DataBaseDBListener"
    arg="dburl=jdbc:odbc:MQIS;user=;password=;logtable=T_Log_SQLLog"/>
    </Listeners>
    <JdbcDrivers>
    <JdbcDriver class="com.microsoft.jdbc.sqlserver.SQLServerDriver"/>
    <JdbcDriver class="sun.jdbc.odbc.JdbcOdbcDriver"/>
    </JdbcDrivers>
    </config>

    "T_Log_SQLLog"的結(jié)構(gòu)是:

    "T_Log_SQLLog"的建庫(kù)腳本在com/cownew/JDBMonitor/listenerImpl/dataBaseListener,(db2.sql,mssqlserver.sql,oracle.sql)。

    DataBaseDBListener是跨數(shù)據(jù)庫(kù)的,你可以把記錄SQL到任何關(guān)系數(shù)據(jù)庫(kù)中。

    FAQ:

    1 如果我暫時(shí)不想記錄SQL語(yǔ)句執(zhí)行怎么辦?難道我要重新修改成原來(lái)的樣子?

    答:無(wú)須如此。您只要修改config.xml,增加<Active>false</Active>到文件中即可。

    如下:

    <config>
    ? <Active> false </Active>
    ? <Listeners>
    ......
    </config>

    如何擴(kuò)展JDBMonitor?

    我們已經(jīng)開(kāi)發(fā)了如下常用的監(jiān)聽(tīng)器:FileDBListener、ConsoleDBListener、 SocketDBListener、DataBaseDBListener。當(dāng)然您也可以開(kāi)發(fā)滿足您要求的監(jiān)聽(tīng)器。所有的監(jiān)聽(tīng)器必須實(shí)現(xiàn)接口:com.cownew.JDBMonitor.commo. IDBListener。IDBListener有兩個(gè)方法需要實(shí)現(xiàn):

    public void init(String arg);
    public void logSql(SQLInfo info);

    JDBMonitor會(huì)將配置文件中監(jiān)聽(tīng)器定義中“arg”的值傳遞給 “init”方法、將代表SQL語(yǔ)句執(zhí)行信息的SQLInfo傳遞給“l(fā)ogSql”方法。

    更多信息請(qǐng)參考API文檔。

    posted @ 2006-05-14 21:42 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(2495) | 評(píng)論 (2)編輯 收藏

    Session Fa?ade 模式

    ? J2EE 項(xiàng)目中 DTO 模式常常是與 Session Fa?ade 模式協(xié)作使用的。為了執(zhí)行一個(gè)業(yè)務(wù)邏輯,經(jīng)常需要訪問(wèn)多個(gè)服務(wù)器端對(duì)象(典型的是實(shí)體 Bean )。這樣出現(xiàn)的問(wèn)題就是多個(gè)細(xì)粒度的對(duì)會(huì)話 Bean 和實(shí)體 Bean 的調(diào)用增加了多個(gè)網(wǎng)絡(luò)調(diào)用的開(kāi)銷(xiāo),而且還有一個(gè)問(wèn)題就是業(yè)務(wù)邏輯被“下放”的客戶端,系統(tǒng)的可維護(hù)性降低。

    比如我們要修改一個(gè)托運(yùn)協(xié)議單,我們首先要找到這個(gè)托運(yùn)協(xié)議單,然后對(duì)其進(jìn)行修改,(其中還要請(qǐng)求托運(yùn)協(xié)議單明細(xì),并對(duì)托運(yùn)協(xié)議單明細(xì)進(jìn)行修改),然后把修改后的結(jié)果發(fā)送到服務(wù)器。如下圖所示:


    ???
    在一次業(yè)務(wù)中客戶端要與服務(wù)器進(jìn)行四次網(wǎng)絡(luò)調(diào)用。而且實(shí)體 Bean 都是具有事務(wù)性的,所以每個(gè)調(diào)用都會(huì)在服務(wù)器端產(chǎn)生一個(gè)獨(dú)立的事務(wù)。而且更加糟糕的是,由于每個(gè)對(duì) EntityBean 的調(diào)用都是一個(gè)獨(dú)立的事務(wù),那么如果在 updateConsignBillMaster 之后, updateConsignBillDetail 的時(shí)候發(fā)生了錯(cuò)誤,那么就會(huì)造成數(shù)據(jù)的不一致,違反了事務(wù)的原子性。

    可見(jiàn)這種方式有如下的缺點(diǎn):

    高昂的網(wǎng)絡(luò)調(diào)用開(kāi)銷(xiāo)

    耦合性太高。客戶端是根據(jù)服務(wù)器端的EntityBean的結(jié)構(gòu)寫(xiě)的,如果服務(wù)器端發(fā)生了改變的話,也必須同時(shí)修改客戶端。

    復(fù)用性不好。修改托運(yùn)協(xié)議單的業(yè)務(wù)邏輯被寫(xiě)到了客戶端,如果以后我們要將UI由jsp網(wǎng)頁(yè)改成applets、或通過(guò)Power Builder等開(kāi)發(fā)工具開(kāi)發(fā)前臺(tái)界面等的時(shí)候,這些業(yè)務(wù)邏輯代碼就必須再此重寫(xiě)。

    開(kāi)發(fā)人員無(wú)法合理分工。在大型項(xiàng)目中,一般都是將表示層(jsp/servlet)、業(yè)務(wù)層(Session Bean)和持久層(Entity Bean)等由不同的程序員來(lái)完成。如果采用我們上邊提到的方法的話,表示層開(kāi)發(fā)人員也必須同時(shí)理解業(yè)務(wù)層和持久層的實(shí)現(xiàn)方式,這樣加大了開(kāi)發(fā)的復(fù)雜度和比較高的出錯(cuò)率。

    無(wú)法保證業(yè)務(wù)的事務(wù)性。

    我們采用Session Fa ? ade模式解決這個(gè)問(wèn)題:我們將實(shí)體Bean包裝在會(huì)話Bean中,客戶端只能訪問(wèn)會(huì)話Bean和不能直接訪問(wèn)實(shí)體Bean。

    采用這種模式后,客戶端和服務(wù)器的交互將會(huì)是這樣的:


    Session Fa
    ? ade模式對(duì)客戶端完全隱藏了存在于服務(wù)器端的對(duì)象模型,這樣也就減少了系統(tǒng)的復(fù)雜性,方便開(kāi)發(fā)人員分工,前臺(tái)表示層開(kāi)發(fā)人員只要調(diào)用Session Bean暴露的接口即可,如果業(yè)務(wù)層發(fā)生了變化,只要暴露的接口不變,那么表示層代碼就不用做任何改變。而且最重要的是:強(qiáng)制一個(gè)業(yè)務(wù)邏輯在一個(gè)網(wǎng)絡(luò)調(diào)用中執(zhí)行,并且使得所有對(duì)Entity Bean的訪問(wèn)都放在同一個(gè)事務(wù)中,這樣就保證了方法調(diào)用的事務(wù)完整性。

    給大家推薦一篇文章
    "寂寞鴕鳥(niǎo)"的網(wǎng)上成功之道
    http://www.cownew.com/showart.asp?id=54
    posted @ 2006-03-29 00:55 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(1284) | 評(píng)論 (1)編輯 收藏

    Decorate( 裝飾者模式 )

    裝飾者模式以對(duì)客戶端透明的方式動(dòng)態(tài)的為對(duì)象增加責(zé)任。此模式提供了一個(gè)比繼承更為靈活的替代方案來(lái)擴(kuò)展對(duì)象的功能,避免了繼承方法產(chǎn)生的類(lèi)激增問(wèn)題,而且更方便更改對(duì)象的責(zé)任。

    我們經(jīng)常要為某一些個(gè)別的對(duì)象增加一些新的職責(zé),并不是全部的類(lèi)。例如我們系統(tǒng)留言反饋板塊中可能需要過(guò)濾用戶輸入留言中的一些詞匯(例如政治敏感詞匯、色情詞匯等)、還可能對(duì)用戶輸入留言進(jìn)行一些修飾(例如對(duì)用戶輸入的 URL 自動(dòng)加上超鏈接、對(duì)用戶輸入的 UBB 代碼進(jìn)行轉(zhuǎn)換的)、還可能將用戶輸入的內(nèi)容定時(shí)發(fā)送的網(wǎng)管的郵箱中等等。如果使用類(lèi)繼承的方式進(jìn)行設(shè)計(jì),我們可能要設(shè)計(jì)一個(gè)接口

    BodyContentFilterIntf ,然后在由 BodyContentFilterIntf 派生出 SensitiveWordContentFilter HtmlContentFilter SendEmailContentFilter 等類(lèi)。但是如果還要要求同時(shí)能過(guò)濾敏感詞匯并能進(jìn)行修飾、或者過(guò)濾敏感詞匯之后把用戶輸入的留言發(fā)送到網(wǎng)管郵箱等等,這樣就要增加 SensitiveWordHtmlContentFilter SensitiveWordSendEmaillContentFilter 等類(lèi),這種方式導(dǎo)致了子類(lèi)瀑發(fā)式的產(chǎn)生。

    一個(gè)靈活的方法是將過(guò)濾器嵌入另一個(gè)過(guò)濾器中,由這個(gè)過(guò)濾器來(lái)負(fù)責(zé)調(diào)用被嵌入過(guò)濾器的方法并執(zhí)行自己的過(guò)濾器方法。 我們稱這個(gè)嵌入的 過(guò)濾器 裝飾( Decorator )。 這個(gè)裝飾與過(guò)濾器接口一致 裝飾 將請(qǐng)求向前轉(zhuǎn)到到 另一個(gè)過(guò)濾器,并且可能能轉(zhuǎn)發(fā)前后執(zhí)行一些額外的動(dòng)作(如 修飾 發(fā)送郵件 ),透明性使你可以遞歸的嵌套多個(gè)裝飾,從面可以添加任意多的功能。

    其實(shí) java 中的過(guò)濾器模式應(yīng)用非常多,典型的就是 IO Stream 操作。在 IO 處理中, Java 將數(shù)據(jù)抽象為流( Stream )。在 IO 庫(kù)中,最基本的是 InputStream OutputStream 兩個(gè)分別處理輸出和輸入的對(duì)象,但是在 InputStream OutputStream 中之提供了最簡(jiǎn)單的流處理方法,只能讀入 / 寫(xiě)出字符,沒(méi)有緩沖處理,無(wú)法處理文件,等等。

    LineNumberInputStream BufferInputStream StringBufferInputStream 等提供各種不同服務(wù)的類(lèi)只要組合起來(lái)就可以實(shí)現(xiàn)很多功能,如下:

    FilterInputStream myStream=new LineNumberInputStream

    ( new BufferInputStream( new StringBufferInputStream( myStringBuffer)));

    多個(gè)的 Decorator 被層疊在一起,最后得到一個(gè)功能強(qiáng)大的流。既能夠被緩沖,又能夠得到行數(shù),這就是 Decorator 的威力!

    我們定義一個(gè)接口 BodyContentFilterIntf 來(lái)定義所有過(guò)濾器要實(shí)現(xiàn)的方法:

    public interface BodyContentFilterIntf {

    ? public String filtContent(String aContent) throws ContentFilterException;

    }

    這個(gè)接口中只有一個(gè)方法 filtContent,將要過(guò)濾的留言傳給aContent參數(shù),filtContent對(duì)aContent進(jìn)行一些處理(如裝飾URL、UBB等),然后將處理后的字符串做為返回值返回;如果留言沒(méi)有通過(guò)過(guò)濾(如含有敏感詞匯等),只要拋出自定義ContentFilterException異常即可。

    下面是一個(gè)可能的一個(gè)過(guò)濾器(保證輸入的字?jǐn)?shù)多于50):

    public class LengthContentFilter

    ??? implements BodyContentFilterIntf {

    ? private BodyContentFilterIntf bodyContentFilterIntf = null;

    ? public HtmlContentFilter(BodyContentFilterIntf aFilter)

    ? {

    ??? bodyContentFilterIntf = aFilter;

    ? }

    ?

    ? public String filtContent(String aContent) throws ContentFilterException {

    ?? String l_Content = aContent;

    ?? If (bodyContentFilterIntf!=null)

    ??? _Content = bodyContentFilterIntf .filtContent(l_Content);

    if (aContent.length()<=50)

    ? throw new ContentFilterException ( 輸入的字?jǐn)?shù)不能少于50! );

    ??? return aContext;

    ?

    ? }

    }

    這是另一個(gè)過(guò)濾器 偽碼 用來(lái)實(shí)現(xiàn)向網(wǎng)管郵箱發(fā)送郵件

    public class SendEmailContentFilter

    ??? implements BodyContentFilterIntf {

    ?

    ? private BodyContentFilterIntf bodyContentFilterIntf = null;

    ? public SendEmailContentFilter(BodyContentFilterIntf aFilter)

    ? {

    ??? bodyContentFilterIntf = aFilter;

    ? }

    ?

    ? public String filtContent(String aContent) throws ContentFilterException {

    ?String l_Content = aContent;

    if (bodyContentFilterIntf!=null)

    l_Content = bodyContentFilterIntf .filtContent(l_Content);

    SendEmail( webmaster@SnailWeb.com ,l_Content)

    ??? return aContext;

    ? }

    }

    當(dāng)然還有 SensitiveWordContextFilter( 過(guò)濾敏感詞匯 ),HtmlContentFilter( 修飾用戶輸入留言中的超級(jí)鏈接 等。

    有了這些過(guò)濾器,我們就可以很方便的為留言版添加各種復(fù)合的過(guò)濾器。例如我們想對(duì)輸入的留言進(jìn)行超鏈接修飾和過(guò)濾敏感詞匯,那么我們只要如下調(diào)用即可:

    try {

    ????????? l_Content = new HtmlContentFilter(new SensitiveWordContextFilter(null)).

    ????????? filtContent(bodyContext);

    ??? }

    ??? catch (ContentFilterException ex) {

    ????? BBSCommon.showMsgInResponse(response, ex.getMessage());

    ????? return;

    }

    我們甚至可以動(dòng)態(tài)的添加不同的過(guò)濾器,例如對(duì)于會(huì)員我們要對(duì)輸入的留言進(jìn)行超鏈接修飾并且將他的留言發(fā)送到網(wǎng)管郵箱,而對(duì)于非會(huì)員我們則要過(guò)濾他輸入的敏感詞匯并且 保證輸入的字?jǐn)?shù)不少于50,我們只要如下調(diào)用即可:

    try {

    ??????? BodyContentFilterIntf bodyContentFilterIntf = null;

    ??????? bodyContentFilterIntf ?= new HtmlContentFilter(null);

    ??????? if(IsMember==true)

    ??????????????? bodyContentFilterIntf ?= new? sendEmailContentFilter ( bodyContentFilterIntf );

    else

    ??????????????? bodyContentFilterIntf ?= new? SensitiveWordContextFilter( bodyContentFilterIntf );?

    l_Content = bodyContentFilterIntf. filtContent(bodyContext);

    ??? }

    ??? catch (ContentFilterException ex) {

    ????? BBSCommon.showMsgInResponse(response, ex.getMessage());

    ????? return;

    }

    關(guān)于其他的設(shè)計(jì)模式的使用我在后續(xù)文章會(huì)繼續(xù)介紹,給大家推薦一個(gè)網(wǎng)站 http://www.cownew.com?,是個(gè)勵(lì)志類(lèi)的,不錯(cuò),看到它的介紹很好,很多文章是從天涯搞下來(lái)的。

    posted @ 2006-03-26 01:46 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(965) | 評(píng)論 (1)編輯 收藏

    DTO模式和SessionFacade模式的應(yīng)用

    ? DTO模式

    我們的系統(tǒng)中經(jīng)常需要在客戶端和服務(wù)器之間傳遞批量數(shù)據(jù) 例如客戶端需要顯示一個(gè)托運(yùn)協(xié)議單 那么客戶端就要向服務(wù)器請(qǐng)求這個(gè)托運(yùn)協(xié)議單中的所有數(shù)據(jù) ConsignDate,StartPort,SenderName 等等 、或者客戶端需要?jiǎng)?chuàng)建、修改或刪除一個(gè)托運(yùn)協(xié)議單。所有這些都會(huì)造成巨大數(shù)量的數(shù)據(jù)在客戶端和服務(wù)器中間交換,這通常可以通過(guò)兩種方法解決:(1)使用一個(gè)有很多參數(shù)的函數(shù)調(diào)用,每個(gè)數(shù)據(jù)項(xiàng)都作為函數(shù)的一個(gè)參數(shù)。例如

    CreateConsignBill(String aBillId, String,Date aConsignDate,String,Port StartPort,String SenderName, …… )

    UpdateConsignBill(String aBillId, String,Date aConsignDate,String,Port StartPort,String SenderName, …… )

    (2)客戶端使用許多細(xì)粒度調(diào)用與服務(wù)器交換數(shù)據(jù)。如下圖


    第一種方式性能比較高,只要在一次網(wǎng)絡(luò)調(diào)用中就可以完成數(shù)據(jù)傳輸,但是缺點(diǎn)是函數(shù)參數(shù)太多,函數(shù)將迅速失去控制,每當(dāng)一個(gè)參數(shù)需要去被增加或刪除,方法簽名需要改變。;第二種方法可以保證調(diào)用的清晰性,但是最大的缺點(diǎn)就是性能問(wèn)題,一次簡(jiǎn)單的讀取數(shù)據(jù)就會(huì)導(dǎo)致大量的網(wǎng)絡(luò)調(diào)用,每個(gè)對(duì)服務(wù)器的調(diào)用是一個(gè)網(wǎng)絡(luò)調(diào)用,

    需要對(duì)返回值序列化和反序列化,當(dāng) ejb 服務(wù)器還要對(duì)每次網(wǎng)絡(luò)調(diào)用進(jìn)行安全檢查,并且如果客戶端沒(méi)有使用 JTA 的客戶分界( client-demarcated )事務(wù),每個(gè)方法調(diào)用可能實(shí)際上在它自己的分離的事務(wù)中執(zhí)行。用這種形式執(zhí)行多個(gè)網(wǎng)絡(luò)調(diào)用將導(dǎo)致嚴(yán)重的性能下降。

    我們的解決方案是生成一個(gè)稱為數(shù)據(jù)傳送對(duì)象( Data Transfer Object,DTO )的普通 Java 類(lèi),它代表一些服務(wù)器端數(shù)據(jù)的快照 , 該對(duì)象在一個(gè)網(wǎng)絡(luò)調(diào)用中封裝了批量數(shù)據(jù)。

    在一個(gè)分布式系統(tǒng)中可以把 DTO 用作讀取操作和更新操作。當(dāng)一個(gè)客戶端需要更新服務(wù)器上的一些數(shù)據(jù)時(shí),它能創(chuàng)建一個(gè)封裝所有服務(wù)器需要去更新的信息的 DTO, 并傳到服務(wù)器去處理,服務(wù)器讀取 DTO 中的數(shù)據(jù),然后進(jìn)行相應(yīng)的處理。當(dāng)一個(gè)客戶端需要服務(wù)器中的數(shù)據(jù)時(shí),只要向服務(wù)器端發(fā)送一個(gè)消息,服務(wù)器將數(shù)據(jù)組裝成 DTO ,然后將此 DTO 做為消息調(diào)用的返回值返回給客戶端。

    下面時(shí)讀取數(shù)據(jù)的活動(dòng)圖

    posted @ 2006-03-21 00:42 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(2100) | 評(píng)論 (1)編輯 收藏

    Decorate(裝飾者模式)

    裝飾者模式以對(duì)客戶端透明的方式動(dòng)態(tài)的為對(duì)象增加責(zé)任。此模式提供了一個(gè)比繼承更為靈活的替代方案來(lái)擴(kuò)展對(duì)象的功能,避免了繼承方法產(chǎn)生的類(lèi)激增問(wèn)題,而且更方便更改對(duì)象的責(zé)任。

    我們經(jīng)常要為某一些個(gè)別的對(duì)象增加一些新的職責(zé),并不是全部的類(lèi)。例如我們系統(tǒng)留言反饋板塊中可能需要過(guò)濾用戶輸入留言中的一些詞匯(例如政治敏感詞匯、色情詞匯等)、還可能對(duì)用戶輸入留言進(jìn)行一些修飾(例如對(duì)用戶輸入的URL自動(dòng)加上超鏈接、對(duì)用戶輸入的UBB代碼進(jìn)行轉(zhuǎn)換的)、還可能將用戶輸入的內(nèi)容定時(shí)發(fā)送的網(wǎng)管的郵箱中等等。如果使用類(lèi)繼承的方式進(jìn)行設(shè)計(jì),我們可能要設(shè)計(jì)一個(gè)接口

    BodyContentFilterIntf,然后在由BodyContentFilterIntf派生出SensitiveWordContentFilterHtmlContentFilterSendEmailContentFilter等類(lèi)。但是如果還要要求同時(shí)能過(guò)濾敏感詞匯并能進(jìn)行修飾、或者過(guò)濾敏感詞匯之后把用戶輸入的留言發(fā)送到網(wǎng)管郵箱等等,這樣就要增加SensitiveWordHtmlContentFilterSensitiveWordSendEmaillContentFilter等類(lèi),這種方式導(dǎo)致了子類(lèi)瀑發(fā)式的產(chǎn)生。

    一個(gè)靈活的方法是將過(guò)濾器嵌入另一個(gè)過(guò)濾器中,由這個(gè)過(guò)濾器來(lái)負(fù)責(zé)調(diào)用被嵌入過(guò)濾器的方法并執(zhí)行自己的過(guò)濾器方法。我們稱這個(gè)嵌入的過(guò)濾器裝飾(Decorator)。這個(gè)裝飾與過(guò)濾器接口一致裝飾將請(qǐng)求向前轉(zhuǎn)到到另一個(gè)過(guò)濾器,并且可能能轉(zhuǎn)發(fā)前后執(zhí)行一些額外的動(dòng)作(如修飾發(fā)送郵件),透明性使你可以遞歸的嵌套多個(gè)裝飾,從面可以添加任意多的功能。

    其實(shí)java中的過(guò)濾器模式應(yīng)用非常多,典型的就是IOStream操作。在IO處理中,Java將數(shù)據(jù)抽象為流(Stream)。在IO庫(kù)中,最基本的是InputStreamOutputStream兩個(gè)分別處理輸出和輸入的對(duì)象,但是在InputStreamOutputStream中之提供了最簡(jiǎn)單的流處理方法,只能讀入/寫(xiě)出字符,沒(méi)有緩沖處理,無(wú)法處理文件,等等。

    LineNumberInputStreamBufferInputStreamStringBufferInputStream等提供各種不同服務(wù)的類(lèi)只要組合起來(lái)就可以實(shí)現(xiàn)很多功能,如下:

    FilterInputStream myStream=new LineNumberInputStream

    ( new BufferInputStream( new StringBufferInputStream( myStringBuffer)));

    多個(gè)的Decorator被層疊在一起,最后得到一個(gè)功能強(qiáng)大的流。既能夠被緩沖,又能夠得到行數(shù),這就是Decorator的威力!

    下面是我們的類(lèi)靜態(tài)圖


        我們定義一個(gè)接口
    BodyContentFilterIntf 來(lái)定義所有過(guò)濾器要實(shí)現(xiàn)的方法:

    public interface BodyContentFilterIntf {

      public String filtContent(String aContent) throws ContentFilterException;

    }

    這個(gè)接口中只有一個(gè)方法filtContent,將要過(guò)濾的留言傳給aContent參數(shù),filtContent對(duì)aContent進(jìn)行一些處理(如裝飾URL、UBB等),然后將處理后的字符串做為返回值返回;如果留言沒(méi)有通過(guò)過(guò)濾(如含有敏感詞匯等),只要拋出自定義ContentFilterException異常即可。

    下面是一個(gè)可能的一個(gè)過(guò)濾器(保證輸入的字?jǐn)?shù)多于50):

    public class LengthContentFilter

        implements BodyContentFilterIntf {

      private BodyContentFilterIntf bodyContentFilterIntf = null;

      public HtmlContentFilter(BodyContentFilterIntf aFilter)

      {

        bodyContentFilterIntf = aFilter;

      }

     

      public String filtContent(String aContent) throws ContentFilterException {

       String l_Content = aContent;

       If (bodyContentFilterIntf!=null)

        _Content = bodyContentFilterIntf .filtContent(l_Content);

    if (aContent.length()<=50)

      throw new ContentFilterException (輸入的字?jǐn)?shù)不能少于50!);

        return aContext;

     

      }

    }

    這是另一個(gè)過(guò)濾器偽碼用來(lái)實(shí)現(xiàn)向網(wǎng)管郵箱發(fā)送郵件

    public class SendEmailContentFilter

        implements BodyContentFilterIntf {

     

      private BodyContentFilterIntf bodyContentFilterIntf = null;

      public SendEmailContentFilter(BodyContentFilterIntf aFilter)

      {

        bodyContentFilterIntf = aFilter;

      }

     

      public String filtContent(String aContent) throws ContentFilterException {

     String l_Content = aContent;

    if (bodyContentFilterIntf!=null)

    l_Content = bodyContentFilterIntf .filtContent(l_Content);

    SendEmail(webmaster@SnailWeb.com,l_Content)

        return aContext;

      }

    }

    當(dāng)然還有SensitiveWordContextFilter(過(guò)濾敏感詞匯),HtmlContentFilter(修飾用戶輸入留言中的超級(jí)鏈接等。

    有了這些過(guò)濾器,我們就可以很方便的為留言版添加各種復(fù)合的過(guò)濾器。例如我們想對(duì)輸入的留言進(jìn)行超鏈接修飾和過(guò)濾敏感詞匯,那么我們只要如下調(diào)用即可:

    try {

              l_Content = new HtmlContentFilter(new SensitiveWordContextFilter(null)).

              filtContent(bodyContext);

        }

        catch (ContentFilterException ex) {

          BBSCommon.showMsgInResponse(response, ex.getMessage());

          return;

    }

    我們甚至可以動(dòng)態(tài)的添加不同的過(guò)濾器,例如對(duì)于會(huì)員我們要對(duì)輸入的留言進(jìn)行超鏈接修飾并且將他的留言發(fā)送到網(wǎng)管郵箱,而對(duì)于非會(huì)員我們則要過(guò)濾他輸入的敏感詞匯并且保證輸入的字?jǐn)?shù)不少于50,我們只要如下調(diào)用即可:

    try {

            BodyContentFilterIntf bodyContentFilterIntf = null;

            bodyContentFilterIntf  = new HtmlContentFilter(null);

            if(IsMember==true)

                    bodyContentFilterIntf  = new  sendEmailContentFilter(bodyContentFilterIntf);

    else

                    bodyContentFilterIntf  = new  SensitiveWordContextFilter(bodyContentFilterIntf); 

    l_Content = bodyContentFilterIntf.filtContent(bodyContext);

        }

        catch (ContentFilterException ex) {

          BBSCommon.showMsgInResponse(response, ex.getMessage());

          return;

    }

    posted @ 2006-03-12 00:00 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(1395) | 評(píng)論 (1)編輯 收藏

    工廠方法模式
       
    以可移植的、可擴(kuò)展的方式來(lái)生成流水號(hào)EJB應(yīng)用中的一個(gè)難點(diǎn)。 現(xiàn)在比較成熟的流水號(hào)生成策略有全局唯一標(biāo)識(shí)(即UUID)和使用數(shù)據(jù)庫(kù)內(nèi)置流水號(hào)生成策略。全局唯一標(biāo)識(shí)有單件模式、根據(jù)網(wǎng)絡(luò)標(biāo)識(shí)(Mac地址+IPJVM唯一對(duì)象標(biāo)識(shí))等策略。不同的數(shù)據(jù)庫(kù)也有不同的流水號(hào)生成策略:例如Oracle采用內(nèi)置流水號(hào)產(chǎn)生機(jī)制,SQL Server則采用Identity機(jī)制。這給我們帶來(lái)方便的同時(shí)也使得應(yīng)用程序在不同系統(tǒng)之間移植變得很麻煩。我采用工廠方法模式解決這個(gè)問(wèn)題。
      
    結(jié)構(gòu)圖


    我們首先定義一個(gè)基類(lèi)接口,它定義了各種唯一序列生成器的共同的方法。
    abstract public interface SequenceCreator {
      abstract public String getSequenceId(String aId);
      abstract public Integer getSequenceAsInt(String aId);
    }
     
    兩個(gè)函數(shù)的參數(shù)aId是不同流水號(hào)生成標(biāo)識(shí)。getSequenceId是產(chǎn)生以字符串形式返回的流水號(hào),getSequenceAsInt是以整形形式返回流水號(hào)。為了防止無(wú)謂的重復(fù),下面的實(shí)例中我們將只寫(xiě)各個(gè)方法的getSequenceId實(shí)現(xiàn)。

    1)我們首先看SQLSequenceCreator的實(shí)現(xiàn)代碼

        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

        Connection con = java.sql.DriverManager.getConnection("jdbc:odbc:DNSEJB");

        CallableStatement cs = con.prepareCall("{call SetIndex(?,?,?)}");

        cs.registerOutParameter(2,Types.VARCHAR);

        cs.setString(1,aId);

        cs.setInt(3,10);

        cs.executeUpdate();

        String str= cs.getString(2);

        return str.substring(aId.length(), str.length());

    我們是調(diào)用我們自定義的存儲(chǔ)過(guò)程來(lái)生成流水號(hào)的,存儲(chǔ)過(guò)程的代碼請(qǐng)參看代碼。

    2Oracle的實(shí)現(xiàn)代碼

    String strSQL = "select " + sequence_name + ".nextval from DUAL";

        Statement  stmt = conn.createStatement();

        ResultSet rs = stmt.executeQuery(strSQL);

        rs.next();

    return rs.getString(1);

    Oracle對(duì)流水號(hào)生成提供了比較好的支持,而且Oracle的生成策略也比SQLServer更高效,消耗更少的資源,資源鎖定情況也比SQLServer少。

    3

    UUID的實(shí)現(xiàn)代碼

    InetAddress inet = InetAddress .getLocalHost();

    Byte[] bytes = inet.getAddress();

    String hexInetAddress = hexFormat(getInt(bytes),8);

    String thisHashCode=hexFormat(System.identityHashCode(this),8);

    MideValue = hexInetAddress+thisHashCode;

    Seeder = new SecureRandom();

    In node = seeder.nextInt();

    Long timeNow = System.currentTimeMillis();

    Int timeLow = (int)timeNow&oxFFFFFFF;

    Int  node = seeder.nextInt();

    Return (hexFormat(timeLow,8)+mid+hexFormat(node,8));

        UUID是一個(gè)基于字符串的主鍵,他有一下字符串組合而成:利用System.currentTimeMillis()精確道毫秒的唯一、IP地址的十六進(jìn)制標(biāo)識(shí)、利用System.identityHashCode(this)得到的一個(gè)JVM內(nèi)部的唯一地址標(biāo)識(shí)和利用隨機(jī)數(shù)生成器生成隨機(jī)數(shù)。

     

    還有很多不同的流水號(hào)生成策略,我們不準(zhǔn)備一一羅列。我們的主要問(wèn)題是要解決在采用不同的序列生成策略時(shí)將代碼的修改減到最小。

    我們定義的SequenceCreator 類(lèi)定義了所有流水號(hào)生成策略公共的方法,并且把這些方法定義為虛方法,在不同的流水號(hào)生成策略代碼中只要覆蓋這些方法即可。序列號(hào)生成器工廠類(lèi)SequenceCreatorFactory getSquenceCreator()并不返回具體的流水號(hào)生成類(lèi),而是返回SequenceCreator,這樣當(dāng)采用不同策略時(shí)只要修改getSquenceCreator方法即可。

    posted @ 2006-03-11 00:11 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(3020) | 評(píng)論 (1)編輯 收藏

         摘要: J2EE項(xiàng)目風(fēng)險(xiǎn) 一、概述 當(dāng)您開(kāi)始著手一個(gè)企業(yè)級(jí)JAVA項(xiàng)目的時(shí)候,您必須對(duì)很多方面進(jìn)行權(quán)衡:供應(yīng)商關(guān)系,為保證完整性在設(shè)計(jì)和開(kāi)發(fā)階段的過(guò)度設(shè)計(jì)。每個(gè)都會(huì)帶來(lái)與生俱來(lái)的的一些風(fēng)險(xiǎn),其中一些是非常明顯的,而其他則不怎么明顯。但是所有這些風(fēng)險(xiǎn)都是可以避免的。在Humphrey Sheil的這篇文章中,他分析了有可能對(duì)企業(yè)級(jí)JAVA項(xiàng)目的成功造成威脅的10個(gè)風(fēng)險(xiǎn),并且描述了避免方法。 在我當(dāng)程序...  閱讀全文
    posted @ 2006-03-10 00:50 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(931) | 評(píng)論 (0)編輯 收藏

      今天看了《一聲嘆息》
     今天在PPLive上重看了一遍《一聲嘆息》。其實(shí)一直都挺喜歡張國(guó)立、彪哥怕的電影的。以前的電影看了以后輕松、開(kāi)心的要命,可這次卻心里一直沉重的要命。我沒(méi)有經(jīng)歷過(guò)婚姻,不能完全體會(huì)其中親情與愛(ài)情的矛盾,但畢竟是已過(guò)已經(jīng)有過(guò)一些人生經(jīng)歷的人,也總能從電影腫體會(huì)中或?qū)蝈e(cuò)的一些東西,也許過(guò)上幾年甚至幾十年再回頭看自己寫(xiě)的這些東西會(huì)感覺(jué)自己很可笑,但是這些也確實(shí)是我真實(shí)的體會(huì)與感受。
      “牽著你的手,就象左手牽右手沒(méi)感覺(jué),但砍下去也會(huì)鉆心的疼”。也許這就是妻子和情人最大的區(qū)別吧。人在這個(gè)社會(huì)上混總會(huì)有各種各樣的誘惑,人也在這些誘惑的拒絕、接受中前行。整個(gè)電影中給我印象最深的是宋曉英,她是我心目中也是很多人心目中的賢妻良母,可是當(dāng)我們遇到李小丹或者王小丹的時(shí)候我們會(huì)怎么做?說(shuō)實(shí)話,真不知道。宋曉英是個(gè)很傻的女人,也是個(gè)很有心計(jì)的女人。


      夫妻本是同林鳥(niǎo),待到天明各自飛。
     

    posted @ 2006-03-09 00:03 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(311) | 評(píng)論 (0)編輯 收藏

          今天改完了bug就開(kāi)始考慮起怎么優(yōu)化數(shù)據(jù)導(dǎo)入的程序了。我們的系統(tǒng)構(gòu)架要求客戶端不能執(zhí)行sql語(yǔ)句,所有的數(shù)據(jù)庫(kù)操作都要通過(guò)ejb來(lái)實(shí)現(xiàn)。我這個(gè)數(shù)據(jù)導(dǎo)入就麻煩了,因?yàn)槭谴罅繑?shù)據(jù)的導(dǎo)入,如果采用ejb的方式一條一條的導(dǎo)入,速度會(huì)很慢。
        所以我采取了定義一個(gè)SessionBean,在SessionBean中定義一個(gè)executeSQL方法,接受兩個(gè)參數(shù),一個(gè)是sql語(yǔ)句(可能帶參數(shù)),和一個(gè)參數(shù)值數(shù)組。這樣客戶端就可以直接通過(guò)sql語(yǔ)句操縱數(shù)據(jù)庫(kù)了。但是問(wèn)題也就來(lái)了,如果每條數(shù)據(jù)都調(diào)用executeSQL訪問(wèn)一次數(shù)據(jù)庫(kù),這樣不僅會(huì)造成頻繁的事務(wù)啟動(dòng),速度很慢,而且由于各個(gè)數(shù)據(jù)庫(kù)插入操作之間是在不同的ejb調(diào)用中進(jìn)行的,所以無(wú)法保證事務(wù)。我優(yōu)化的重點(diǎn)當(dāng)然也就在這兩點(diǎn)上。項(xiàng)目緊急,我不能對(duì)構(gòu)架做太大的改動(dòng)了,因?yàn)楫吘挂郧暗膶?shí)現(xiàn)方式可以導(dǎo)入數(shù)據(jù)了,我就琢磨著在不做大規(guī)模改動(dòng)的情況下進(jìn)行優(yōu)化,將風(fēng)險(xiǎn)降低到最小。
        系統(tǒng)中所有ejb都是基于接口的,比如上邊定義的executeSQL方法就定義在IImportDataFacade接口中,ejb實(shí)現(xiàn)這個(gè)接口,客戶端通過(guò)工廠方法ImportDataFactory.getInstance()訪問(wèn)這個(gè)接口(ImportDataFactory.getInstance()返回IImportDataFacade類(lèi)型)。好,我就從他下手。定義一個(gè)ImportDataDecorate類(lèi),讓他也實(shí)現(xiàn)IImportDataFacade接口,它的executeSQL實(shí)現(xiàn)不是吧sql提交到數(shù)據(jù)庫(kù),而是把它緩存起來(lái),等所有插入語(yǔ)句執(zhí)行完畢后將緩存的sql語(yǔ)句一次性提交到我定義的一個(gè)新的接口方法中(此方法含有一個(gè)sql數(shù)組的發(fā)那個(gè)法),這樣就可以保證事務(wù)和速度了。
        我是怎么實(shí)現(xiàn)對(duì)系統(tǒng)改動(dòng)最小呢?對(duì)了,我只要把所有調(diào)用ImportDataFactory.getInstance().executeSQL()的地方替換成new ImportDataDecorate(ImportDataFactory.getInstance()).executeSQL(),哈哈,改動(dòng)很小吧,而且一旦發(fā)現(xiàn)這種實(shí)現(xiàn)方式不可行,那么只要將ImportDataDecorate.executeSQL()的實(shí)現(xiàn)改成直接提交到數(shù)據(jù)庫(kù)就好了,其他調(diào)用根本不用變。設(shè)計(jì)模式很偉大呀,只不過(guò)我都不知道我用的這是什么模式,Proxy 還是Decorator?不知道,反正解決問(wèn)題了,呵呵。
    posted @ 2006-03-07 22:08 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(1005) | 評(píng)論 (7)編輯 收藏

    1、人為了成功 總會(huì)失去些最本性的東西
    要想得到一些東西必須要失去一些東西,只有失去一些東西才能得到一些東西,成功的人是得到的東西的價(jià)值大于失去的,失敗的人是失去的東西的價(jià)值大于得到的東西
    但是往往失去的是人性中最美好的東西  
    美好的東西不等于有價(jià)值的東西,明白這個(gè)道理,你就成熟了,但是也就“俗”了 。那些美好的東西早晚有一天要失去的,你去盡力挽留他只會(huì)使你受的傷害更多
    2、不知道從什么時(shí)候開(kāi)始,再也不敢叫“男孩”“女孩”了,因?yàn)槲覀兌家呀?jīng)是“人”了 。
    3、每個(gè)人女孩都是天使,除去它們那身白色羽毛,你會(huì)發(fā)現(xiàn)她們不過(guò)是一群吸血蝙蝠
    4、人有時(shí)流淚并不是多么愛(ài)著對(duì)方,而通常是自己感動(dòng)自己,對(duì)曾經(jīng)的付出的心血感到悲傷
    5、以前我以為是個(gè)文學(xué)家,等我開(kāi)始每天寫(xiě)blog以來(lái)我才發(fā)現(xiàn),我TMD簡(jiǎn)直就是個(gè)文學(xué)家
    posted @ 2006-03-06 23:00 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(395) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共30頁(yè): First 上一頁(yè) 22 23 24 25 26 27 28 29 30 下一頁(yè) 
    主站蜘蛛池模板: 2022免费国产精品福利在线 | 久久国产免费观看精品3| 日本免费一区二区三区四区五六区 | 久久国产免费观看精品3| 亚洲AV无码一区二区乱孑伦AS| 亚洲色图国产精品| 亚洲妇女熟BBW| 四虎精品成人免费视频| 亚洲免费精彩视频在线观看| 男人的好免费观看在线视频| 九月婷婷亚洲综合在线| 亚洲精品国产啊女成拍色拍 | 永久免费无码日韩视频| 国产成人毛片亚洲精品| 亚洲1234区乱码| 两个人日本WWW免费版| 浮力影院第一页小视频国产在线观看免费 | 9久热精品免费观看视频| 99久久久精品免费观看国产| 亚洲黄片毛片在线观看| 国产亚洲精品bv在线观看| 成年大片免费视频| 亚洲毛片在线观看| 免费可以看黄的视频s色| 亚洲色无码一区二区三区| 亚洲另类无码专区首页| 99在线视频免费| 亚洲熟妇丰满xxxxx| 91免费福利精品国产| 亚洲精品亚洲人成在线播放| 无码av免费网站| 亚洲三级高清免费| 亚洲一级Av无码毛片久久精品| 久久精品视频免费看| 亚洲国产成人精品女人久久久| 亚洲无圣光一区二区| 18观看免费永久视频| 亚洲va国产va天堂va久久| 999在线视频精品免费播放观看| 国产一区二区三区亚洲综合| 成人啪精品视频免费网站|