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

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

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

    如鵬網 大學生計算機學習社區

    CowNew開源團隊

    http://www.cownew.com 郵件請聯系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

    #

    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    我準備給JDBMonitor增加一個性能監測報表的功能。用戶在“報表條件”中填寫要統計的起始時間、結束時間和單位時間后,點擊查詢。程序從DataBaseDBListener記錄的表T_LOG_SQLLog中進行統計并顯示報表。例如:用戶在起始時間中輸入”2006-5-30 18:00:00”,結束時間輸入”2006-6-1 12:00:00”,時間單位選擇“5分鐘”,點擊“查詢”。程序將把T_LOG_SQLLog中FbeginTime大于等于”2006-5-30 18:00:00”,小于等于”2006-6-1 12:00:00”的記錄過濾出來。然后統計每5分鐘記錄的條數(也就是數據庫執行的次數),以時間序列圖的形式顯示成報表。
    比如:
    fid?????? ftime
    1?2006-05-05 10:00:00.000
    2?2006-05-05 10:00:01.000
    3?2006-05-05 10:00:10.000
    4?2006-05-05 10:01:10.000
    5?2006-05-05 10:01:20.000

    這樣的數據屬于離散的數據,因為數據庫的執行時間是不確定的,要把它們按統計它們的出現次數常常需要使用數據挖掘的東西。數據挖掘通常都是不同的數據庫有不同的實現的,JDBMonitor是跨數據庫的,因此肯定不能使用這些數據庫特有的東西。現在也有一些開源的跨數據庫的數據挖掘引擎,但是其尺寸巨大無比,都要50M以上。JDBMonitor是一個小的工具,為了方便部署和使用,JDBMontior的一個基本原則就是盡量避免使用JDK之外的類,所以肯定不能使用它們。我經過仔細思考,發現可以通過如下技巧來解決:

    select count(sub.f) as exeCount,min(sub.FBeginTime) as FTime from(
    select cast(DateDiff(ss,?,FBeginTime)/? as int) as f,FBeginTime from T_LOG_SQLLog
    )as sub
    where 1=1
    and FBeginTime>=?
    and FBeginTime<=?
    group by sub.f
    order by sub.f ASC


    其中第一、三個參數傳遞用戶選擇的時間段的起始時間,第二個參數是用戶選擇的計時間隔(以秒為單位),參數四是用戶選擇的時間段的結束時間。
    我采用的是整除的技巧來實現的這個效果。
    其中FBeginTime是SQL語句執行的開始時間(在這里我們就把它看作SQL語句的執行時間),cast(DateDiff(ss,?,FBeginTime)/? as int) as f的意思就是計算SQL語句的執行時間到選擇的時間段的起始時間之間的秒間隔數,然后再整除用戶選擇的計時間隔(以秒為單位)。經過整除以后同一個時間段內的數據就相同了,然后我們一個groupby,然后一個count(sub.f),這樣各個時間段sql的執行次數就出來了。
    以上邊的數據為例,假如我輸入的起始時間是2006-05-05 10:00:00.000,結束時間是2006-05-05 10:02:00.000。
    那么select cast(DateDiff(ss,?,FBeginTime)/? as int) as f,FBeginTime from T_LOG_SQLLog的結果集就是:
    f? FBeginTime
    0 2006-05-05 10:00:00.000?
    0 2006-05-05 10:00:01.000?
    0 2006-05-05 10:00:10.000
    1 2006-05-05 10:01:00.000
    1 2006-05-05 10:01:00.000?
    然后,以f為分組條件進行匯總,并統計f的count,這樣各個時間段sql的執行次數就出來了:
    3 2006-05-05 10:00:00.000?
    2 2006-05-05 10:01:00.000?
    當然不同的數據庫的計算日期時間差和截取整數的方式是略有差異的,我這里用的是mssqlserver的語法。

    posted @ 2006-06-12 01:30 CowNew開源團隊 閱讀(1080) | 評論 (0)編輯 收藏

    我上上個月申請java.net的開源服務,沒想到前兩天才收到抄送給我的郵件,收件人是java.net的另外一個工作人員,發件人要收件人,批準我的請求:
    發件人:"Eric Renaud"
    收件人:leads@javatools.dev.java.net
    抄送:cownew@dev.java.net
    主題:New Java.net Request to JavaTools - jdbmonitor

    To: JavaTools Community Leaders -

    https://jdbmonitor.dev.java.net/

    This project has been moved to your inbox for review.
    Please approve or disapprove ASAP.
    ......
    工作效率太慢了,我回郵件道:

    The working efficiency too lowered!
    My request to sourceforge already approved last month,I don't need your webhosting service?anymore,thanks? all the same!
    沒想到今天竟然收到一封中文郵件:

    對不起,你要主辦項目jdbmonitor的請求你被否決。你再也不能為項目jdbmonitor訪問任何資源。
    以下是否決的理由:
    Project
    owner moved to sourceforge, so, he does not want to host it at java.net
    anymore.
    關于更多信息,請聯系fabiane (@dev.java.net)”
    呵呵,原來不光中國人辦事效率低呀。
    posted @ 2006-06-10 22:47 CowNew開源團隊 閱讀(264) | 評論 (0)編輯 收藏

    CowNew開源團隊網站 http://www.cownew.com
    論壇??? http://www.cownew.com/newpeng/
    轉載請注明此版權信息。

    ORM在整個java社區使用越來越廣泛,但是隨著更多的項目使用ORM,很多人也感到了它的不足:慢,甚至慢的讓人無法忍受!可是讓我們從ORM的原理仔細思考一下,就會發現,使用ORM并不會明顯降低運行速度。因為無論什么ORM工具都是根據對象去動態構造SQL語句,執行的,相信無論構造SQL的速度多么慢,那和數據庫操作比起來,幾乎是可以忽略不計的。但是為什么確實又那么慢呢?歸根結底,是對ORM的使用不當造成的。
    1、陋習:過渡依賴ORM的Update和delete。比如,將某個人的年齡加3,很多人就會如下寫:
    PersonInfo p = orm.getPerson(...);
    p.setAge(p.getAge);
    orm.update(p);
    看看,這一來一回就要兩個sql語句,先取數據:select age,id,.... from T_Person,然后再update,update T_Person set age=23....。
    相信沒有ORM,誰也不會去這么寫。直接寫sql:update T_Person set age=age+3 where...這不很好嗎?速度不會快多了嗎?
    又如:刪除年齡為15的人,有的人就敢這么寫:
    PersonInfo persons[] = orm.getPersons("age=15");
    for(int i=0,n=persons.length;i<n;i++)
    {
    ?? orm.delete(persons[i]);
    }

    我真的要瘋了,它真的不懂delete from T_person where age=15嗎??
    根據我個人的經驗如果要發揮ORM的最大作用,同時最大程度的避免其副作用,我建議最好只使用orm的addNew(增加數據)和get***Info(從數據庫中取數據)的功能,而對update,delete則直接寫sql,這樣最好。
    ORM+JDBC,優美和效率的最佳結合點。
    2、認為ORM萬能。在寫一些報表的時候甚至也有人用orm取出數據,然后通過代碼來出報表。相信稍微復雜一點的報表就能把人搞死。所以報表,千萬不能用ORM,直接寫SQL是最好的事情。

    posted @ 2006-06-09 01:33 CowNew開源團隊 閱讀(853) | 評論 (0)編輯 收藏

    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息
    ???????
    ??????? 昨天發現JDBMonitor在多數據源的情況下會有問題,這個問題就是對單例模式理解不深造成的。為了減少系統中的對象數目,我用單例模式設計DBLogger,也就是提供一個getLogger方法返回一個日志處理器,getLogger則返回的是一個緩存了的DBLogger實例。昨天我用一個大型的信息系統測試了一下,發現當有多個數據源存在的時候,所有的日志都記錄到了第一個啟動的JDBMonitor的配置文件指定的監聽器中了。經過分析得知,雖然多個數據源啟動了多個JDBMonitor,但是由于這些JDBMonitor實例是運行在同一個JVM中的,而一個類變量在同一個JVM是唯一的,所以這些實例調用getLogger的時候得到的都是第一個JDBMonitor中配置的了。
    ??????? 我采用如下方式解決:為getLogger增加一個connectionId參數,將原先的單例去掉,改成一個hash表的靜態變量instanceMap。在調用getLogger的時候,先以connectionId為key到instanceMap中找是不是已經有一個實例了,如果有則直接返回這個實例,否則構造一個DBLogger,將此DBLogger以connectionId為key保存到instanceMap中,然后返回實例。
    ??????? 根據JDBMonitor的功能特點配置文件的路徑就可以做為這個connectionId了,也就是如果是多個數據源指向一個配置文件,那么這幾個數據源其實還是共用一個DBLogger,這個也是合理的,而且也可以節省很多資源。
    ??????? 從這個例子我們可以看出,單例模式并不一定是只創建一個實例這么簡單。Log4j的getLogger就是很好的證明。
    ??????? 但是多個數據源共用一個DBLogger又引來了另一個問題,就是當有一個數據源的Connection被close掉以后,DBLogger也會隨之close掉,其他數據源再訪問的時候就會報錯。我采用類似GC、COM等的引用機制解決此問題。在DBLogger內部維護一個計數器refCounter,初始值是0,當調用getLogger訪問到此實例的時候,就refCounter自動加1,當調用DBLogger的close的時候就自動減1,當refCounter降到0的時候就說明沒有對象引用到它了,這個時候再釋放DBLogger中的各種資源。當然addRef、releaseRef、close等方法都要標識成synchronized的。
    ??????? 同理,以前的這些channel、dbListeners類變量也要改成實例變量。consumerthread也要改成實例變量,在close中再關閉這個線程。這樣就保證了每一個JDBMonitor都有自己的消費者線程。
    ??????? 為了使語意更加明確,我將getLogger重命名為createLogger。
    ??????? 代碼已經提交到CVS,今天晚些時候將打包放到團隊網站上。
    ??????? 向大家匯報,SQL解析引擎已經有階段成果,強類型AST節點都已定義完畢,也已經可以生成最簡單的CommonAST。

    ?

    posted @ 2006-06-06 20:55 CowNew開源團隊 閱讀(900) | 評論 (0)編輯 收藏

    ??? 為了測試我的一個業務系統在不同數據庫上的表現,我的tomcat上配置了多個數據源,這樣我可以輕松的切換系統到不同的數據源上。為了監測每個數據源的運行狀況,隨時觀測執行的sql語句,我為每個數據源都配置了JDBMonitor,并且這些數據源的JDBMonitor的配置文件共用一個config.xml文件。

    ??? 但是在我運行的時候卻發現系統報錯“java.net.bindexception:? address? in? use:? jvm_bind”,根據我三十多年的從醫經驗判斷,俺認為是端口沖突。。。。。。唉,別扔臭雞蛋呀,呵呵。原來是我在config.xml中配置了SocketDBListener,端口為默認的9527,這樣當第一個數據源使用以后,這個數據源將啟動一個SocketDBListener,所以9527端口就被占用了,以后其他的數據源被時候以后在啟動SocketDBListener的時候,也嘗試去監聽9527端口,這樣就出現了如上面的錯誤。解決問題很簡單:為每個數據源都指定一個不同的配置文件(比如config1.xml,config2.xml),并且在每個配置文件中都配置不同的端口(比如9527、9528、3721、9981等等,只要不互相重復,并且不與系統中其他軟件占用的端口沖突即可)。
    ??
    ?? JDBMonitor今天修改了一個在一個JVM中啟動多個JDBMonitor的bug。已經提交到CVS,并更新網站下載。
    posted @ 2006-06-06 01:49 CowNew開源團隊 閱讀(511) | 評論 (0)編輯 收藏

    作者楊中科是CowNew開源團隊JDBMonitor項目組的開發人員。
    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    我們經常需要將我們的程序運行中的一些信息(比如在選項對話框中的設置)記錄下來,以做便再次運行的時候不用再重寫填寫這些數據。這對改善軟件的人機可用性方面是很有用的。但是讓人失望的是,現在很多Java開源軟件在這一點做的很不好,每次運行都要用戶去填寫那些配置文件。做為最好用的數據庫監控、日志工具,JDBMonitor在這方面做的是非常好的,以它的Swing界面監視器和數據庫日志記錄查詢窗口中所有的配置信息(例如遠程服務器地址、端口、數據庫名稱、JDBC驅動等等)都是被保存的,當再次運行的時候程序會自動加載這些配置信息,所以使用起來相當方便。
    我們接下來就來分析一下JDBMonitor是如何實現的。JDBMonitor的二進制jar包和源代碼都可以從 http://www.cownew.com 下載得到。
    保存加載配置文件有多種方式,比如xml文件、properties文件等,采用這些保存方式的一個問題就是如果程序是以jar,war 包等方式發布的那么這些配置文件就不能放在包中,因為包中的文件是不能在運行時改動的,只能放在磁盤的文件中,但是放在磁盤的文件中又很容易出現因為操作系統的差異、權限等問題造成程序的問題。JDBMonitor采用的則是JDK中的Preferences類來避免這些問題。
    JDK1.4中提供了Preferences類,在java.util.prefs包里面。Preferences類在不同的平臺中有不同的實現方式。比如在Windows平臺中,Preferences是將數據保存在注冊表中的。

    為了區分不同的應用程序的參數項,在建立Preferences時要指定一個節點路徑。
    Preferences是一個抽象類,提供了一系列靜態方法和抽象方法來操作參數項:
    ?Preferences userData = Preferences.userNodeForPackage(this); //得到用戶配置節點
    ?Preferences sysData = Preferences.systemNodeForPackage(this); //得到系統配置節點。
    比如在windows中Preferences.userNodeForPackage代表得到 HKEY_CURRENT_USER\Software\JavaSoft\Prefs下的相對路徑
    Preferences.systemNodeForPackage代表得到? HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs下的相對路徑

    Preferences的讀取、存儲是非常容易的,存儲只要調用put***方法就可以,讀取調用get***即可,不同的put,get方法分別用于存取不同的數據類型,詳細信息可以參考JavaDoc。
    以JDBMonitor的Swing界面監視器的連接對話框為例為大家分析,打開com.cownew.JDBMonitor.listenerImpl.sckListenerClient.ConnectConfigDialog,saveConfig()和loadConfig()分別就是保存和讀取參數用了,這兩個方法會在超類中被調用。可以看到代碼實現非常簡單:
    protected void saveConfig()
    ?{
    ? Preferences prefer = Preferences.userNodeForPackage(getClass());
    ? prefer.put(HOST_NAME,getHostName());
    ? prefer.putInt(PORT,getPort());
    ?}
    ?
    ?protected void loadConfig()
    ?{
    ? Preferences prefer = Preferences.userNodeForPackage(getClass());
    ? setHostName(prefer.get(HOST_NAME,""));
    ? setPort(prefer.getInt(PORT,9527));
    ?}

    posted @ 2006-06-02 23:48 CowNew開源團隊 閱讀(964) | 評論 (0)編輯 收藏

    作者楊中科是CowNew開源團隊JDBMonitor項目組的開發人員。
    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    數據庫監控、日志工具JDBMonitor在介紹文檔中說到“JDBMonitor另起一個線程來記錄SQL,所以它不會對程序運行速度有任何影響。”,那么它是如何做到的呢?
    JDBMonitor采用“生產者-消費者模型”完成此功能。學過操作系統原理的朋友對“生產者-消費者模型”一定不陌生,它是和“哲學家進餐問題”等相提并論的經典模型。
    JDBMonitor的主線程做為“生產者”,產生“日志信息”這個產品,另起一個線程做為消費者,這個消費者負責“消費”日志信息,并把日志信息派發給所有的監聽者,這樣日志的產生和消費是獨立的,所以無論日志的派發有多慢,都沒有關系,都不會影響到主線程的運行速度。下面讓我們深入研究一下:
    (注:JDBMonitor的二進制jar包和源代碼都可以從 http://www.cownew.com 下載得到。)
    打開com.cownew.JDBMonitor.common.DBLogger。JDBMonitor每次截獲到一條sql語句,都會調用logSQL方法,并把sql語句的信息對象傳過來,這樣我們就可以把logSQL方法當成生產者,logsql把消息放到channel中。LogConsumer是一個實現了Runnable接口的類,它就是日志的消費者,并且是運行于另一個線程的,它負責實時檢測channel,只要channel中有東西,他就從channel取出日志對象,然后發送給各個監聽器。
    startConsumer中
    for (;;)
    {
    ? SQLInfo info = (SQLInfo) channel.take();
    ? for (int i = 0, n = dbListeners.length; i < n; i++)
    ? {
    ??? dbListeners[i].logSql(info);
    ? }
    }
    就是在實時檢測channel中的產品。
    channel是一個阻塞通道BlockedChannel的實例,這個阻塞通道主要提供兩個方法offer,take,offer方法向通道中放入產品,take從通道中取產品,當通道中沒有產品的時候,take方法將會阻塞,直到有產品為止。BlockedChannel是靠java的wait-notify機制實現的,原理非常簡單,有興趣的朋友看一下其實現代碼就可以。
    值得注意的是,LogConsumer是一個后臺線程,因為如果LogConsumer不是后臺線程,那么由于LogConsumer一直在無限循環里執行,所以程序就不能正常終止。而設置為后臺線程后,在其他工作線程停止后,此線程就會自動終止。關于“后臺線程”的知識,可以查看相關資料。
    但是采用后臺線程以后,又有另一個問題出現了,在主線程停止后,有可能產品通道channel中還有沒有發送完的日志信息,這樣就會造成漏記日志信息。
    Runtime 類有一個addShutDownHook方法,可以調用此方法向JVM注冊一個監聽器,這個監聽器必須實現Thread接口,在JVM停止之前,這個監聽器將會被運行,這樣我們就可以在JVM停止之前做一些事情了。
    JDBMonitor就是用addShutDownHook解決此問題的。見DBLogger的靜態初始化塊:

    Runtime.getRuntime().addShutdownHook(new Thread(){
    ? public void run()
    ? {
    ??? //once JVM will shutDown,this hook will pause the shutingdown
    ??? //until all the SQLInfo be dispatched
    ??? while (!channel.isEmpty())
    ??? {
    ????? try
    ????? {
    ??????? Thread.sleep(SHUTDOWNSLEEPMSECOND);
    ????? } catch (Exception e)
    ????? {
    ??????? throw CommonUtils.toRuntimeException(e);
    ????? }
    ??? }
    ??? ...
    ?? }
    });?

    在JVM停止之前會首先檢測產品通道中有沒有產品,如果還有,則會一直等到產品被消費完后再終止。

    ?while (!channel.isEmpty())
    ??? {
    ????? try
    ????? {
    ??????? Thread.sleep(SHUTDOWNSLEEPMSECOND);
    ????? } catch (Exception e)
    ????? {
    ??????? throw CommonUtils.toRuntimeException(e);
    ????? }
    ??? }

    posted @ 2006-06-02 23:46 CowNew開源團隊 閱讀(943) | 評論 (0)編輯 收藏

    作者楊中科是CowNew開源團隊JDBMonitor項目組的開發人員。
    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    ? 有一定開發經驗的朋友在處理異常的時候都不會直接寫個e.printstacktrace()來“捕獲”異常,但是在有些情況下是“無法拋出”異常的,比如一些重載基類的一些方法,但是這些方法是沒有聲明異常拋出的,或者在類的static初始化塊的時候也是“無法拋出”異常的。其實“無法拋出異常”的地方還是能拋出運行時異常的。
    最好用的數據庫監控、日志工具JDBMonitor就是通過這種方式解決此問題的。JDBMonitor的二進制jar包和源代碼都可以從 http://www.cownew.com 下載得到。
    JDBMonitor在CommonUtils總定義了一個toRuntimeException方法,用來把異常轉換成運行時異常:
    public static RuntimeException toRuntimeException(Throwable e)
    {
    ?RuntimeException re = new RuntimeException(e);
    ?re.setStackTrace(e.getStackTrace());
    ?return re;
    }
    讓我們首先打開com.cownew.JDBMonitor.jdbc.DBDriver,然后定位到代碼的最后
    static
    {
    ??? try
    ??? {
    ?DriverManager.registerDriver(new DBDriver());
    ??? } catch (Exception e)
    ??? {
    ?throw CommonUtils.toRuntimeException(e);
    ??? }
    }
    這是在類的初始化塊中向DriverManager注冊JDBC驅動,在初始化塊中是不能聲明拋出異常的,因此JDBMonitor將異常轉化為RuntimeException異常拋出。這樣就做到了不放過任何一個異常。

    再打開:
    com.cownew.JDBMonitor.listenerImpl.sckListenerClient.ListenerClient.java中的SocketListener類,其中的run方法是實現的Runnable接口中的方法,而Runnable接口中的Run方法是沒有聲明異常的,因此JDBMonitor也是采用的轉換成RuntimeException的方式進行的異常處理:
    public void run()
    {
    ? try
    ? {
    ?...
    ? } catch (IOException e)
    ? {
    ??? throw CommonUtils.toRuntimeException(e);
    ? } catch (ClassNotFoundException e)
    ? {
    ??? throw CommonUtils.toRuntimeException(e);
    ? }
    }

    posted @ 2006-06-02 23:46 CowNew開源團隊 閱讀(813) | 評論 (0)編輯 收藏

    作者楊中科是CowNew開源團隊JDBMonitor項目組的開發人員。
    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    正則表達式是一個非常強大的工具,有了這個工具,在進行字符串的解析、修改等不會再麻煩,比寫一堆if else語句更清晰易懂。
    關于正則表達式的基礎知識我這里不再多講,大家可以到網上查找相關的資料。本文假定您已經熟悉正則表達式的基本使用。
    讓我們以最好用的數據庫監控、日志工具JDBMonitor為例來講解。JDBMonitor的二進制jar包和源代碼都可以從 http://www.cownew.com 下載得到。
    DataBaseDBListener要讀取形如"dburl=jdbc:odbc:MQIS;user=sa;password=sa;logtable=T_Log_Log"的配置字符串,然后從中解析數據庫連接配置、表名等信息,并且user=sa;password和logtable部分也是可以忽略的(這是當然的,因為有的數據庫不需要用戶名密碼,而且logtable也有默認值)。
    打開com.cownew.JDBMonitor.listenerImpl.DataBaseDBListener,init就是進行參數arg的解析的:
    1、Pattern patAll = Pattern.compile("dburl=(.+?);?(user=.*;password=.*;)?(logtable=.+)?");
    這句是從arg中提取三個部分,分別是dburl部分,用戶名密碼部分,logtable部分。因為用戶名密碼部分,logtable部分是可以忽略的,因此采用"?"來標識這個兩個分組“(user=.*;password=.*;)?”、“(logtable=.+)?”。而一旦dburl部分,用戶名密碼部分忽略,那么dburl=...后的;也是可以忽略的,因此";?"。
    值得我們注意的是“dburl=(.+?)”,為什么不是"dburl=(.+)"呢?怎么多了個?。你可以嘗試去掉“?”后,再次運行。你會看到dburl=后所有的字符,包括用戶名密碼部分,logtable部分都被看成dburl=的值了,也就是后邊的字符都被吃掉了。為什么呢?
    這就要提到正則表達式的貪婪性和懶惰性,關于貪婪性和懶惰性可以查看網上一篇文章《深入淺出之正則表達式》(http://dragon.cnblogs.com/archive/2006/05/08/394078.html)。
    象《深入淺出之正則表達式》描述的那樣:“+”是貪婪的。也就是說,“+”會導致正則表達式引擎試圖盡可能的重復前導字符。只有當這種重復會引起整個正則表達式匹配失敗的情況下,引擎會進行回溯。也就是說,它會放棄最后一次的“重復”,然后處理正則表達式余下的部分。一個用于修正以上問題的可能方案是用“+”的惰性代替貪婪性。你可以在“+”后面緊跟一個問號“?”來達到這一點。“*”,“{}”和“?”表示的重復也可以用這個方案。
    因此JDBMonitor就采用了dburl=(.+?)來解決這個貪婪性問題。
    2、Pattern patUserPwd = Pattern.compile("user=(.*);password=(.*);");
    在第一步中把“user=sa;password=sa;”當成一個整體來提取,那么我們接下來還要從這個提取中的串中提取用戶名user、密碼password信息。因此采用這種方式來提取。這種分步提取的方式比寫復雜的正則表達式一次性提取看起來更清晰,更加易維護。

    posted @ 2006-06-02 23:43 CowNew開源團隊 閱讀(910) | 評論 (0)編輯 收藏

    作者楊中科是CowNew開源團隊JDBMonitor項目組的開發人員。
    CowNew開源團隊網站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉載請注明此版權信息

    我個人是極力反對不必要的downcasting的,但是在使用java的集合類的時候確是不可避免的,因為JDK5之前的集合中只能存儲Object類型,所以看到一個List的時候,你也不知道里邊放的是什么數據類型,只能膽戰心驚的來下轉型:Integer i = (Integer)list.get(i)。
    好在JDK5可以使用泛型了,這個問題也就迎刃而解了。這樣就再也不會去去問其他開發人員“你List里放的是什么類型的對象?”,再也不會望著一大堆以“老祖先”形式表現的object了發呆了,終于可以看到容器中存的這些對象的類型了。
    但是在有的情況下我們還是不能使用JDK5的,比如你的正在開發的系統是基于JDK1.4的,那么遷移到JDK5是有一定風險的,或者你開發的模塊要被JDK5一下的程序使用的,那么就暫時放棄JDK5的這個新特性了。
    那么沒有泛型我們就沒法解決這個問題了嗎?非也!鳥槍!呵呵。
    一種方式是自己包裝一下List寫一個自己的專有數據類型的List,比如
    class IntegerList()
    {
    ?? private List list;
    ?? ......
    ?? public void add(Integer i)
    ?? {
    ???? list.add(i);
    ?? }
    ?? public Integer get(int i)
    ?? {
    ????? return (Integer)list.get(i);
    ?? }
    }
    這樣做的缺點就是對每個數據類型都要生成一個集合類,無疑加大了代碼量。
    另一種方式就是使用數組解決此問題,因為數組中的數據類型是清晰的,比如Integer[] ia = new Integer[5];,一眼就可以看出其中存儲的是什么類型。
    最好用的數據庫監控、日志工具JDBMonitor就是通過這種方式解決此問題的。JDBMonitor的二進制jar包和源代碼都可以從 http://www.cownew.com 下載得到。
    打開com.cownew.JDBMonitor.jdbc.connect
    定位到:
    List lisList = configInfo.getListenerInfoList();
    DBListenerInfo[] dbListenerInfos = new DBListenerInfo[lisList.size()];
    for(int i=0,n=lisList.size();i<n;i++)
    {
    ??? DBListenerInfo lisInfo = (DBListenerInfo) lisList.get(i);
    ??? dbListenerInfos[i] = lisInfo;
    }????
    return new DBConnection(cn,dbListenerInfos);??
    程序把多個監聽器對象信息DBListenerInfo拼轉成DBListenerInfo數組,然后傳遞給DBConnection。
    DBConnection接收到dbListenerInfos會把它轉發給DBLogger做為其構造函數的參數:
    private DBLogger(DBListenerInfo[] dbListenerInfos)
    這樣在DBLogger內部就可以很清晰的知道dbListenerInfos中的數據類型了:
    for(int i=0,n=dbListenerInfos.length;i<n;i++)
    {
    ?? ...
    ?? DBListenerInfo info = dbListenerInfos[i];
    ?? ...
    }

    在系統的接口邊界處傳遞的數據類型非常明確,不會因為傳遞一個光禿禿的List而不知道其類型,然后膽戰心驚的進行類型轉換了。
    因此我認為在一個方法或者類的內部可以采用List等進行數據的處理,但是當需要與外部(相對于類來說就是其他類,相對于方法來說就是其他方法)交換多個同構對象的時候,最好轉換成數組傳遞,這樣就清晰多了。

    posted @ 2006-06-02 23:41 CowNew開源團隊 閱讀(744) | 評論 (0)編輯 收藏

    僅列出標題
    共30頁: First 上一頁 20 21 22 23 24 25 26 27 28 下一頁 Last 
    主站蜘蛛池模板: 亚洲精品福利你懂| 亚洲2022国产成人精品无码区 | 亚洲午夜爱爱香蕉片| 人人狠狠综合久久亚洲| 永久免费观看的毛片的网站| 亚洲高清有码中文字| 免费高清资源黄网站在线观看| 亚洲日韩中文字幕无码一区| 毛片免费在线播放| 亚洲欧美成人av在线观看| 国产成人免费a在线资源| 国产亚洲Av综合人人澡精品| 亚洲精品无码av天堂| 韩国免费A级毛片久久| 亚洲av无码专区国产乱码在线观看 | 亚洲综合色区中文字幕| 日韩免费一区二区三区| 成人久久久观看免费毛片| 亚洲熟妇无码八AV在线播放| 免费无码一区二区三区| 亚洲三级在线视频| 四虎永久免费地址在线观看| 巨胸喷奶水www永久免费| 97亚洲熟妇自偷自拍另类图片| 国国内清清草原免费视频99| 亚洲熟妇AV乱码在线观看| 亚洲国产成人精品女人久久久| a毛片在线还看免费网站| 亚洲一线产区二线产区精华| 青青青国产色视频在线观看国产亚洲欧洲国产综合| 亚洲AV无码一区二区三区久久精品| 亚洲人成网站18禁止一区| 18pao国产成视频永久免费| 亚洲av日韩专区在线观看| 国产亚洲综合色就色| 青春禁区视频在线观看直播免费| 免费VA在线观看无码| 亚洲综合一区二区| 亚洲AV无码一区二区三区国产| 99热在线精品免费播放6| 美女啪啪网站又黄又免费|