2008年6月26日 #

          java 數(shù)據(jù)庫(kù)緩沖池 使用c3p0

          c3p0很容易使用的開(kāi)源專(zhuān)業(yè)級(jí)jdbc數(shù)據(jù)庫(kù)緩沖池。
          它是sourceforge上的一個(gè)開(kāi)源項(xiàng)目,
          項(xiàng)目在
          http://sourceforge.net/projects/c3p0
          他的眾多特性這里就不一一介紹了。
          比較爽的一點(diǎn)就是
          當(dāng)Connection歸還緩沖池時(shí),c3p0會(huì)很小心的關(guān)閉
          這條連接打開(kāi)的Statement和ResultSet,免去了使用時(shí)
          自己動(dòng)手小心翼翼的關(guān)閉。

          c3p0使用非常簡(jiǎn)單,這里給一個(gè)例子

          package common.db;

          import java.sql.Connection;
          import java.sql.SQLException;
          import java.util.Properties;


          import com.mchange.v2.c3p0.ComboPooledDataSource;
          import com.mchange.v2.c3p0.DataSources;

          public final class ConnectionManager {
          ?private static ConnectionManager instance;
          ?
          ?public ComboPooledDataSource ds;
          ?private static String c3p0Properties="c3p0.properties";
          ?
          ?private ConnectionManager() throws Exception {
          ??Properties p = new Properties();
          ??p.load(this.getClass().getResourceAsStream(c3p0Properties));
          ??ds = new ComboPooledDataSource();
          ?}
          ?
          ?public static final ConnectionManager getInstance() {
          ??if (instance == null) {
          ???try {
          ????instance = new ConnectionManager();
          ???} catch (Exception e) {
          ????e.printStackTrace();
          ???}
          ??}
          ??return instance;
          ?}
          ?
          ?public synchronized final Connection getConnection() {
          ??try {
          ???return ds.getConnection();
          ??} catch (SQLException e) {
          ???e.printStackTrace();
          ??}
          ??return null;
          ?}

          ?protected void finalize() throws Throwable {
          ??DataSources.destroy(ds);?//關(guān)閉datasource
          ??super.finalize();
          ?}
          ?
          }

          然后在ConnectionManager類(lèi)的目錄下再創(chuàng)建一個(gè)配置文件c3p0.properties
          內(nèi)容如下:
          #db login parameters
          driverClass=com.mysql.jdbc.Driver
          jdbcUrl=jdbc:mysql://localhost/test?useUnicode=no&characterEncoding=GBK
          user=test
          password=test

          #pool parameters
          initialPoolSize=2
          maxPoolSize=5
          #maxIdleTime=10
          #idleConnectionTestPeriod=5
          autoCommitOnClose=true

          完整的配置文件參數(shù)參看c3p0的文檔

          使用connection時(shí)很簡(jiǎn)單
          Connection conn = ConnectionManager.getInstance().getConnection();
          ...
          最后 conn.close() 即可,

          posted @ 2008-10-23 10:24 金家寶 閱讀(4355) | 評(píng)論 (2)編輯 收藏

          JDBC也分2.0和3.0?

          如題。研究中...以前沒(méi)有注意過(guò)。

          posted @ 2008-10-23 10:10 金家寶 閱讀(299) | 評(píng)論 (0)編輯 收藏

          鯉魚(yú)論壇 研究筆記(未)

          2008.10.21第一天
          網(wǎng)站地址: http://www.liyunet.com/
          源碼下載: http://www.liyunet.com/bbs/download.jsp

          我主要是利用該論壇的簡(jiǎn)易性來(lái)研究JSP技術(shù),以及緩存技術(shù)。雖然說(shuō)目前大部分論壇應(yīng)用的都是主流框架技術(shù),但說(shuō)回來(lái),這些框架也只是對(duì)JSP等相關(guān)技術(shù)的一個(gè)封裝,而了解底部應(yīng)用及其原理更容易讓我理解主流框架的內(nèi)部原理機(jī)制。不至于讓框架把我們變成“傻子”。


          那就開(kāi)始吧
          首先,和某些大蝦一樣的習(xí)慣,我們從WEB-INF下的web.xml開(kāi)始,從以下代碼中可以發(fā)現(xiàn)隨著tomcat啟動(dòng)時(shí),自動(dòng)加載了InitServlet類(lèi)。這是一個(gè)Servlet類(lèi)。
          WEB-INF\web.xml部分代碼:
          1
          2<servlet-name>InitServlet</servlet-name>
          3????????<servlet-class>com.bcxy.servlet.InitServlet</servlet-class>
          4????????<load-on-startup>1</load-on-startup>
          5??????</servlet>
          6

          查看com.bcxy.servlet.InitServlet類(lèi),代碼很簡(jiǎn)單:
          開(kāi)始做了一個(gè)對(duì)此類(lèi)日志(log4j)的綁定。接著通過(guò)SystemConfig取得了系統(tǒng)配置中的連接類(lèi)型conntype(查看classes目錄下的SystemConfig.xml可知此變量是判斷使用連接池的類(lèi)型0:3P0; 1:Proxool)。接著是初始化操作,記錄一些必要的啟動(dòng)信息(log4j)(其中做了本地地址和網(wǎng)絡(luò)訪問(wèn)地址的轉(zhuǎn)換)。
          用DBUtil.close測(cè)試連接池是否加載成功。
          最后是釋放類(lèi)所做的必要操作。判斷使用的是哪一種連接池,然后關(guān)閉。這樣我們的第一個(gè)類(lèi)就分析完畢。
          接著需要了解到
          SystemConfig類(lèi)是加載SystemConfig.xml配置文件,并設(shè)定方法去讀取。其中有一定的類(lèi)型轉(zhuǎn)換。

          此時(shí)似乎已經(jīng)找不到頭緒了。那這樣吧。我們就開(kāi)始訪問(wèn)我們自己搭建的論壇,從首頁(yè)開(kāi)始,也就是index.jsp頁(yè)面。
          瀏覽index.jsp代碼,由上向下理解每一個(gè)語(yǔ)句的含義(整體分體)。

          設(shè)定頁(yè)面編碼;導(dǎo)入IPLocalizer類(lèi)(應(yīng)該是做IP顯示的工具類(lèi));插入INC/const.jsp頁(yè)(過(guò)后會(huì)有分析);設(shè)定stats變量數(shù)值(通過(guò)閱讀其他jsp頁(yè)面發(fā)現(xiàn),此變量的作用主要是在于在首頁(yè)顯示用戶狀態(tài)時(shí),兼并顯示當(dāng)前用戶做瀏覽的頁(yè)面:也就是stats的值,這樣我們可以在客戶可訪問(wèn)的范圍內(nèi)對(duì)stats變量進(jìn)行設(shè)置,就可以查看在線用戶的當(dāng)前行為);繼續(xù)插入INC/theme.jsp(估計(jì)是定制論壇模板的文件);<table>標(biāo)簽內(nèi)部就是連接到相關(guān)顯示數(shù)據(jù)信息的jsp頁(yè)面并附加了參數(shù)。其中的一些格式是通過(guò)上面引用文件中的變量設(shè)置,相對(duì)不難理解;論壇消息廣播部分,通過(guò)一個(gè)可執(zhí)行jsp頁(yè)面vector顯示在首頁(yè)頂部,當(dāng)中訪問(wèn)數(shù)據(jù)庫(kù)的細(xì)節(jié)需要進(jìn)一步研究代碼);接著是帖子的遍歷,也就是首頁(yè)最關(guān)鍵的部分,這里看起來(lái)不是由jsp頁(yè)面來(lái)負(fù)責(zé)獲取數(shù)據(jù),而是通過(guò)Forum類(lèi)來(lái)獲取一些過(guò)濾之后的數(shù)據(jù):這里所說(shuō)的過(guò)濾是例如置頂帖子,最新帖子等有一些特殊標(biāo)記的數(shù)據(jù):;
          index.jsp的其他部分就都是大同小異了。都是通過(guò)一個(gè)遍歷來(lái)展現(xiàn)具有相同特性的數(shù)據(jù)。;大家需要注意一些關(guān)于頁(yè)面表現(xiàn)的而非java技術(shù)的部分,例如信息層的提示,和一些圖片連接。
          通過(guò)index.jsp的學(xué)習(xí),我們大概已經(jīng)了解了大部分jsp頁(yè)面代碼的表現(xiàn)形式和含義。當(dāng)然,一定要注意在這個(gè)過(guò)程中,參數(shù)傳遞、參數(shù)獲取的代碼部分,不要遺漏。除了一些我們可以看到的頁(yè)面之外,上面部分也講到了一些并不用于顯示給用戶的頁(yè)面,這里我們認(rèn)為它是可執(zhí)行頁(yè)面,也就是說(shuō)它對(duì)我們的數(shù)據(jù)和請(qǐng)求做了一些處理,或者說(shuō)把我們的請(qǐng)求轉(zhuǎn)交給了服務(wù)器(比如servlet)。

          預(yù)計(jì)晚上要研究一下有關(guān)數(shù)據(jù)庫(kù)方面的存取類(lèi)JdbcWrapper以及連接獲取和釋放、數(shù)據(jù)查詢插入。
          2008.10.22
          大概昨天寫(xiě)的已經(jīng)忘的差不多了,那么我們還是從index.jsp文件開(kāi)始,前幾行沒(méi)有什么問(wèn)題,都是一些導(dǎo)入文件的標(biāo)簽,那么我們從SkinUtil.這個(gè)類(lèi)入手。在查看SkinUtil類(lèi)代碼的時(shí)候我們發(fā)現(xiàn)里面應(yīng)用了一些com\bcxy\bbs\util?包中類(lèi),其中含有三個(gè)工具類(lèi)。(偷笑,看了文件大小,應(yīng)該代碼不多,我們看看里面都是什么)在開(kāi)始之前我們應(yīng)了解一下GCookie.java類(lèi)的大概內(nèi)容和作用??磳?dǎo)入包我們可以大概了解一下此類(lèi)的作用:對(duì)URL的編碼與解碼,產(chǎn)生和讀取Cookie,還有就是做一些日志記錄(log4j)。
          我們仔細(xì)閱讀后,了解到,其中有一個(gè)重載方法,也就是setCookie方法,根據(jù)不同的參數(shù),可以讓我們選擇直接賦予變量名和值的方法,或者是賦予變量名和值另外加上最大保存時(shí)間的方法。? 類(lèi)中的另一個(gè)方法是獲取Cookie方法值。
          ParamUtil類(lèi)也很簡(jiǎn)單,是取得字符串和 取得整數(shù)的重載方法,其中的參數(shù)決定是否有默認(rèn)值,是否需要轉(zhuǎn)碼。
          SysUtil類(lèi)中根據(jù)SystemConfig類(lèi)中的讀取方法讀取配置文件systemconfig.properties,按照里面的設(shè)置,來(lái)判斷是否對(duì)參數(shù)和數(shù)據(jù)庫(kù)讀取操作中的參數(shù)進(jìn)行編碼。其中還有一個(gè)方法是取得真實(shí)地址,當(dāng)然這些都是根據(jù)systemconfig.properties文件中配置而定的。
          BBSCconst.java類(lèi)簡(jiǎn)單的設(shè)置了一些常量。作用是設(shè)置數(shù)據(jù)庫(kù)表名的時(shí)候加上systemconfig.properties中設(shè)置的前綴。
          回到SkinUtil.java類(lèi)似乎看起來(lái)一些剛剛還陌生的類(lèi)方法,顯得明朗。前面設(shè)置了一個(gè)Cookie的變量名并賦了值。

          ret?=?new?JdbcWrapper().doIntSearch(sql,?0);

          這里用到了新類(lèi),也就是我們昨天說(shuō)過(guò)的要了解的關(guān)于數(shù)據(jù)庫(kù)連接的類(lèi)。也是今天要解決的重點(diǎn)。打開(kāi)JdbcWrapper類(lèi),查看代碼.(插一句,看代碼的時(shí)候,我覺(jué)得先看包名,了解大概要用到的類(lèi)和方法,去設(shè)想這個(gè)類(lèi)要實(shí)現(xiàn)的功能),yi一眼看來(lái),大概都熟悉,無(wú)非是連接數(shù)據(jù)庫(kù) 讀取,結(jié)果保存,異常,還有一些類(lèi)似數(shù)組的HashMap還有遍歷用得Iterator。想想,大概就是數(shù)據(jù)層的一些基礎(chǔ)CRUD操作。但是其中有個(gè)類(lèi)不是很熟悉,DatabaseMetaData類(lèi),查看sun公司的在線文檔,發(fā)現(xiàn)這是個(gè)接口而且方法奇多,文檔的第一句這么寫(xiě),

          Comprehensive?information?about?the?database?as?a?whole.?

          我也不能理解這句話包含了什么內(nèi)容。不管他,在程序中慢慢體會(huì)吧。JdbcWrapper這個(gè)類(lèi)有點(diǎn)長(zhǎng),不過(guò),大部分方法都有類(lèi)似的作用,也就是說(shuō)真正不同功能的代碼也只有幾分之一而已。我看的都想睡覺(jué)了。

          在網(wǎng)吧,因?yàn)椴槐悖入x開(kāi)咯
          今天還好,自己有一臺(tái)電腦,可以不限制時(shí)間。繼續(xù)工作....
          之前研究JdbcWrapper類(lèi)的時(shí)候有一個(gè)小小的疑問(wèn)。如下

          ?

          ?1?????//######這里有一點(diǎn)不明白,為什么要判斷getAutoClose()
          ?2????/*
          ?3?????*?當(dāng)需要事務(wù)支持時(shí),需要設(shè)置autoClose=false,那就等到事務(wù)提交時(shí)再關(guān)閉數(shù)據(jù)庫(kù)連接。
          ?4?????*?*/

          ?5????public?void?closeConnection()?{
          ?6????????if?(getAutoClose())?{
          ?7????????????DBUtil.close(pstmt,?con);
          ?8????????}

          ?9????}

          10

          今天看群里鯉魚(yú)回答內(nèi)容如下:

          當(dāng)需要事務(wù)支持時(shí),需要設(shè)置autoClose=false,那就等到事務(wù)提交時(shí)再關(guān)閉數(shù)據(jù)庫(kù)連接。


          一時(shí)還沒(méi)有理解開(kāi)來(lái)。
          看過(guò)來(lái)看過(guò)去,JdbcWrapper類(lèi)對(duì)我來(lái)講還是有一部分難以理解。索性不去管它,等在下面的代碼中出現(xiàn)時(shí),反復(fù)查閱應(yīng)該會(huì)有更多的收獲。

          posted @ 2008-10-21 11:47 金家寶 閱讀(368) | 評(píng)論 (0)編輯 收藏

          關(guān)于正則表達(dá)式

          *匹配除了換行之外的所有字符

          合法IP的正則表達(dá)式 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

          \s匹配任意的空白符、(空格、制表符、換行符、中文全角空格)
          \w匹配字母或數(shù)字或下劃線或漢字

          表1.常用的元字符
          代碼說(shuō)明
          .匹配除換行符以外的任意字符
          \w匹配字母或數(shù)字或下劃線或漢字
          \s匹配任意的空白符
          \d匹配數(shù)字
          \b匹配單詞的開(kāi)始或結(jié)束
          ^匹配字符串的開(kāi)始
          $匹配字符串的結(jié)束


          表2.常用的限定符
          代碼/語(yǔ)法說(shuō)明
          *重復(fù)零次或更多次
          +重復(fù)一次或更多次
          ?重復(fù)零次或一次
          {n}重復(fù)n次
          {n,}重復(fù)n次或更多次
          {n,m}重復(fù)n到m次


          后向引用

          使用小括號(hào)指定一個(gè)子表達(dá)式后,匹配這個(gè)子表達(dá)式的文本(也就是此分組捕獲的內(nèi)容)可以在表達(dá)式或其它程序中作進(jìn)一步的處理。默認(rèn)情況下,每個(gè)分組會(huì)自動(dòng)擁有一個(gè)組號(hào),規(guī)則是:從左向右,以分組的左括號(hào)為標(biāo)志,第一個(gè)出現(xiàn)的分組的組號(hào)為1,第二個(gè)為2,以此類(lèi)推。

          后向引用用于重復(fù)搜索前面某個(gè)分組匹配的文本。例如,\1代表分組1匹配的文本。難以理解?請(qǐng)看示例:

          \b(\w+)\b\s+\1\b可以用來(lái)匹配重復(fù)的單詞,像go go, 或者kitty kitty。這個(gè)表達(dá)式首先是一個(gè)單詞,也就是單詞開(kāi)始處和結(jié)束處之間的多于一個(gè)的字母或數(shù)字(\b(\w+)\b),這個(gè)單詞會(huì)被捕獲到編號(hào)為1的分組中,然后是1個(gè)或幾個(gè)空白符(\s+),最后是分組1中捕獲的內(nèi)容(也就是前面匹配的那個(gè)單詞)(\1)。

          你也可以自己指定子表達(dá)式的組名。要指定一個(gè)子表達(dá)式的組名,請(qǐng)使用這樣的語(yǔ)法:(?<Word>\w+)(或者把尖括號(hào)換成'也行:(?'Word'\w+)),這樣就把\w+的組名指定為Word了。要反向引用這個(gè)分組捕獲的內(nèi)容,你可以使用\k<Word>,所以上一個(gè)例子也可以寫(xiě)成這樣:\b(?<Word>\w+)\b\s+\k<Word>\b

          使用小括號(hào)的時(shí)候,還有很多特定用途的語(yǔ)法。下面列出了最常用的一些:

          表4.常用分組語(yǔ)法
          分類(lèi)代碼/語(yǔ)法說(shuō)明
          捕獲(exp)匹配exp,并捕獲文本到自動(dòng)命名的組里
          (?<name>exp)匹配exp,并捕獲文本到名稱(chēng)為name的組里,也可以寫(xiě)成(?'name'exp)
          (?:exp)匹配exp,不捕獲匹配的文本,也不給此分組分配組號(hào)
          零寬斷言(?=exp)匹配exp前面的位置
          (?<=exp)匹配exp后面的位置
          (?!exp)匹配后面跟的不是exp的位置
          (?<!exp)匹配前面不是exp的位置
          注釋(?#comment)這種類(lèi)型的分組不對(duì)正則表達(dá)式的處理產(chǎn)生任何影響,用于提供注釋讓人閱讀


          表5.懶惰限定符
          代碼/語(yǔ)法說(shuō)明
          *?重復(fù)任意次,但盡可能少重復(fù)
          +?重復(fù)1次或更多次,但盡可能少重復(fù)
          ??重復(fù)0次或1次,但盡可能少重復(fù)
          {n,m}?重復(fù)n到m次,但盡可能少重復(fù)
          {n,}?重復(fù)n次以上,但盡可能少重復(fù)


          表6.常用的處理選項(xiàng)
          名稱(chēng)說(shuō)明
          IgnoreCase(忽略大小寫(xiě))匹配時(shí)不區(qū)分大小寫(xiě)。
          Multiline(多行模式)更改^$的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個(gè)字符串的開(kāi)頭和結(jié)尾匹配。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結(jié)束前的位置.)
          Singleline(單行模式)更改.的含義,使它與每一個(gè)字符匹配(包括換行符\n)。
          IgnorePatternWhitespace(忽略空白)忽略表達(dá)式中的非轉(zhuǎn)義空白并啟用由#標(biāo)記的注釋。
          RightToLeft(從右向左查找)匹配從右向左而不是從左向右進(jìn)行。
          ExplicitCapture(顯式捕獲)僅捕獲已被顯式命名的組。
          ECMAScript(JavaScript兼容模式)使表達(dá)式的行為與它在JavaScript里的行為一致。
          表7.尚未詳細(xì)討論的語(yǔ)法
          代碼/語(yǔ)法說(shuō)明
          \a報(bào)警字符(打印它的效果是電腦嘀一聲)
          \b通常是單詞分界位置,但如果在字符類(lèi)里使用代表退格
          \t制表符,Tab
          \r回車(chē)
          \v豎向制表符
          \f換頁(yè)符
          \n換行符
          \eEscape
          \0nnASCII代碼中八進(jìn)制代碼為nn的字符
          \xnnASCII代碼中十六進(jìn)制代碼為nn的字符
          \unnnnUnicode代碼中十六進(jìn)制代碼為nnnn的字符
          \cNASCII控制字符。比如\cC代表Ctrl+C
          \A字符串開(kāi)頭(類(lèi)似^,但不受處理多行選項(xiàng)的影響)
          \Z字符串結(jié)尾或行尾(不受處理多行選項(xiàng)的影響)
          \z字符串結(jié)尾(類(lèi)似$,但不受處理多行選項(xiàng)的影響)
          \G當(dāng)前搜索的開(kāi)頭
          \p{name}Unicode中命名為name的字符類(lèi),例如\p{IsGreek}
          (?>exp)貪婪子表達(dá)式
          (?<x>-<y>exp)平衡組
          (?im-nsx:exp)在子表達(dá)式exp中改變處理選項(xiàng)
          (?im-nsx)為表達(dá)式后面的部分改變處理選項(xiàng)
          (?(exp)yes|no)把exp當(dāng)作零寬正向先行斷言,如果在這個(gè)位置能匹配,使用yes作為此組的表達(dá)式;否則使用no
          (?(exp)yes)同上,只是使用空表達(dá)式作為no
          (?(name)yes|no)如果命名為name的組捕獲到了內(nèi)容,使用yes作為表達(dá)式;否則使用no
          (?(name)yes)同上,只是使用空表達(dá)式作為no

          posted @ 2008-10-17 11:10 金家寶 閱讀(331) | 評(píng)論 (1)編輯 收藏

          Lucene倒排索引原理(轉(zhuǎn))

          Lucene是一個(gè)高性能的java全文檢索工具包,它使用的是倒排文件索引結(jié)構(gòu)。該結(jié)構(gòu)及相應(yīng)的生成算法如下:

          0)設(shè)有兩篇文章1和2
          文章1的內(nèi)容為:Tom?lives?in?Guangzhou,I?live?in?Guangzhou?too.
          文章2的內(nèi)容為:He?once?lived?in?Shanghai.

          1)由于lucene是基于關(guān)鍵詞索引和查詢的,首先我們要取得這兩篇文章的關(guān)鍵詞,通常我們需要如下處理措施
          a.我們現(xiàn)在有的是文章內(nèi)容,即一個(gè)字符串,我們先要找出字符串中的所有單詞,即分詞。英文單詞由于用空格分隔,比較好處理。中文單詞間是連在一起的需要特殊的分詞處理。
          b.文章中的”in”,?“once”?“too”等詞沒(méi)有什么實(shí)際意義,中文中的“的”“是”等字通常也無(wú)具體含義,這些不代表概念的詞可以過(guò)濾掉
          c.用戶通常希望查“He”時(shí)能把含“he”,“HE”的文章也找出來(lái),所以所有單詞需要統(tǒng)一大小寫(xiě)。
          d.用戶通常希望查“l(fā)ive”時(shí)能把含“l(fā)ives”,“l(fā)ived”的文章也找出來(lái),所以需要把“l(fā)ives”,“l(fā)ived”還原成“l(fā)ive”
          e.文章中的標(biāo)點(diǎn)符號(hào)通常不表示某種概念,也可以過(guò)濾掉
          在lucene中以上措施由Analyzer類(lèi)完成

          經(jīng)過(guò)上面處理后
          ????文章1的所有關(guān)鍵詞為:[tom]?[live]?[guangzhou]?[i]?[live]?[guangzhou]
          ????文章2的所有關(guān)鍵詞為:[he]?[live]?[shanghai]

          2)?有了關(guān)鍵詞后,我們就可以建立倒排索引了。上面的對(duì)應(yīng)關(guān)系是:“文章號(hào)”對(duì)“文章中所有關(guān)鍵詞”。倒排索引把這個(gè)關(guān)系倒過(guò)來(lái),變成:“關(guān)鍵詞”對(duì)“擁有該關(guān)鍵詞的所有文章號(hào)”。文章1,2經(jīng)過(guò)倒排后變成
          關(guān)鍵詞???文章號(hào)
          guangzhou??1
          he?????????2
          i???????????1
          live???????1,2
          shanghai???2
          tom?????????1

          通常僅知道關(guān)鍵詞在哪些文章中出現(xiàn)還不夠,我們還需要知道關(guān)鍵詞在文章中出現(xiàn)次數(shù)和出現(xiàn)的位置,通常有兩種位置:a)字符位置,即記錄該詞是文章中第幾個(gè)字符(優(yōu)點(diǎn)是關(guān)鍵詞亮顯時(shí)定位快);b)關(guān)鍵詞位置,即記錄該詞是文章中第幾個(gè)關(guān)鍵詞(優(yōu)點(diǎn)是節(jié)約索引空間、詞組(phase)查詢快),lucene中記錄的就是這種位置。

          加上“出現(xiàn)頻率”和“出現(xiàn)位置”信息后,我們的索引結(jié)構(gòu)變?yōu)椋?br />關(guān)鍵詞???文章號(hào)[出現(xiàn)頻率]???出現(xiàn)位置
          guangzhou?1[2]???????????????3,6
          he???????2[1]???????????????1
          i?????????1[1]???????????????4
          live??????1[2],2[1]???????????2,5,2
          shanghai??2[1]???????????????3
          tom??????1[1]???????????????1

          以live 這行為例我們說(shuō)明一下該結(jié)構(gòu):live在文章1中出現(xiàn)了2次,文章2中出現(xiàn)了一次,它的出現(xiàn)位置為“2,5,2”這表示什么呢?我們需要結(jié)合文章號(hào)和出現(xiàn)頻率來(lái)分析,文章1中出現(xiàn)了2次,那么“2,5”就表示live在文章1中出現(xiàn)的兩個(gè)位置,文章2中出現(xiàn)了一次,剩下的“2”就表示live是文章2中第 2個(gè)關(guān)鍵字。
          ????
          以上就是lucene索引結(jié)構(gòu)中最核心的部分。我們注意到關(guān)鍵字是按字符順序排列的(lucene沒(méi)有使用B樹(shù)結(jié)構(gòu)),因此lucene可以用二元搜索算法快速定位關(guān)鍵詞。
          ????
          實(shí)現(xiàn)時(shí)?lucene將上面三列分別作為詞典文件(Term?Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。其中詞典文件不僅保存有每個(gè)關(guān)鍵詞,還保留了指向頻率文件和位置文件的指針,通過(guò)指針可以找到該關(guān)鍵字的頻率信息和位置信息。

          ????Lucene中使用了field的概念,用于表達(dá)信息所在位置(如標(biāo)題中,文章中,url中),在建索引中,該field信息也記錄在詞典文件中,每個(gè)關(guān)鍵詞都有一個(gè)field信息(因?yàn)槊總€(gè)關(guān)鍵字一定屬于一個(gè)或多個(gè)field)。

          ???? 為了減小索引文件的大小,Lucene對(duì)索引還使用了壓縮技術(shù)。首先,對(duì)詞典文件中的關(guān)鍵詞進(jìn)行了壓縮,關(guān)鍵詞壓縮為<前綴長(zhǎng)度,后綴>,例如:當(dāng)前詞為“阿拉伯語(yǔ)”,上一個(gè)詞為“阿拉伯”,那么“阿拉伯語(yǔ)”壓縮為<3,語(yǔ)>。其次大量用到的是對(duì)數(shù)字的壓縮,數(shù)字只保存與上一個(gè)值的差值(這樣可以減小數(shù)字的長(zhǎng)度,進(jìn)而減少保存該數(shù)字需要的字節(jié)數(shù))。例如當(dāng)前文章號(hào)是16389(不壓縮要用3個(gè)字節(jié)保存),上一文章號(hào)是16382,壓縮后保存7(只用一個(gè)字節(jié))。
          ????
          ????下面我們可以通過(guò)對(duì)該索引的查詢來(lái)解釋一下為什么要建立索引。
          假設(shè)要查詢單詞?“l(fā)ive”,lucene先對(duì)詞典二元查找、找到該詞,通過(guò)指向頻率文件的指針讀出所有文章號(hào),然后返回結(jié)果。詞典通常非常小,因而,整個(gè)過(guò)程的時(shí)間是毫秒級(jí)的。
          而用普通的順序匹配算法,不建索引,而是對(duì)所有文章的內(nèi)容進(jìn)行字符串匹配,這個(gè)過(guò)程將會(huì)相當(dāng)緩慢,當(dāng)文章數(shù)目很大時(shí),時(shí)間往往是無(wú)法忍受的。

          posted @ 2008-10-17 09:43 金家寶 閱讀(2846) | 評(píng)論 (1)編輯 收藏

          struts2標(biāo)簽

          ?

          一、
          寫(xiě)jsp頁(yè)面的時(shí)候,在struts2中,用的是s標(biāo)記,先引入標(biāo)記:
          <%@ taglib prefix="s" uri="/struts-tags"%>
          二、
          struts2的標(biāo)簽和1是完全不同的。
          struts2的標(biāo)簽分為兩大類(lèi):非UI標(biāo)志和UI標(biāo)志 struts1 將標(biāo)志庫(kù)按功能分成HTML、Tiles、Logic和Bean等幾部分
          下面就介紹strut2的具體標(biāo)簽:
          1、UI
          UI標(biāo)志又可以分為表單UI和非表單UI兩部分。表單UI部分基本與Struts 1.x相同,都是對(duì)HTML表單元素的包裝。不過(guò),Struts 2.0加了幾個(gè)我們經(jīng)常在項(xiàng)目中用到的控件如:datepicker、doubleselect、timepicker、optiontransferselect等。因?yàn)檫@些標(biāo)志很多都經(jīng)常用到,而且參數(shù)也很多,要在一篇文章詳細(xì)說(shuō)明并非易事。
          下面主要是ui標(biāo)簽的一些用法
          form:
          <s:form action="exampleSubmit" method="post" enctype="multipart/form-data">
          <s:submit />
          ??? <s:reset />

          </s:form>可以上傳文件的form。
          textfield:
          <s:textfield
          ??????????? label="姓名:"
          ??????????? name="name"
          ??????????? tooltip="Enter your Name here" />
          datepicker:
          <s:datepicker
          ??????????? tooltip="Select Your Birthday"
          ??????????? label="生日"
          ??????????? name="birthday" />
          textarea:
          <s:textarea
          ??????????? tooltip="Enter your remart"
          ??????????? label="備注"
          ??????????? name="remart"
          ??????????? cols="20"
          ??????????? rows="3"/>
          select:
          <s:select
          ??????????? tooltip="Choose user_type"
          ??????????? label=""
          ??????????? list="#{'free':'免費(fèi)','vip':'收費(fèi)'}" value="#{'free':'免費(fèi)'}"??
          ?????????? name="bean.user_type"
          ??????????? emptyOption="true"
          ??????????? headerKey="None"
          ??????????? headerValue="None"/>
          <s:select
          ??????????? tooltip="Choose user_type"
          ??????????? label=""
          ??????????? list="#{'free':'免費(fèi)','vip':'收費(fèi)'}" value="#{'free':'免費(fèi)'}"??
          ?????????? name="bean.user_type"
          ??????????? emptyOption="true"
          ??????????? headerKey="None"
          ??????????? headerValue="None"/>
          <s:select
          list="venderList"
          listKey="id"
          listValue="name"
          value="%{profile.companyName}"
          name="companyName" cssClass="sel_style_w_180"/>??
          挺好用的
          checkboxlist:
          <s:checkboxlist
          ??????????? tooltip="Choose your Friends"
          ??????????? label="朋友"
          ??????????? list="{'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}"
          ??????????? name="friends"/>
          checkbox:
          ?? <s:checkbox
          ??????????? tooltip="Confirmed that your are Over 18"
          ??????????? label="年齡"
          ??????????? name="legalAge"
          ??????????? value="18"/>
          file:
          ?? <s:file
          ??????????? tooltip="Upload Your Picture"
          ??????????? label="Picture"
          ??????????? name="picture" />
          a:
          <s:a href="getP.jsp">超鏈接提交</s:a>
          date :
          <s:date name="ad_end_time" format="yyyy-MM-dd"/>


          2、非UI
          if、elseif和else 描述:
          執(zhí)行基本的條件流轉(zhuǎn)。
          參數(shù):
          名稱(chēng)必需默認(rèn)類(lèi)型描述備注test是Boolean決定標(biāo)志里內(nèi)容是否顯示的表達(dá)式else標(biāo)志沒(méi)有這個(gè)參數(shù)id否Object/String用來(lái)標(biāo)識(shí)元素的id。在UI和表單中為HTML的id屬性 例子:
          <%@ page c %>
          <%@ taglib prefix="s" uri="/struts-tags" %>
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html>
          ??? <head>
          ??????? <title>Condition Flow</title>
          ??? </head>
          ??? <body>
          ??????? <h3>Condition Flow</h3>????????????
          ??????? <!--
          ??????????? 這里有點(diǎn)小技巧:
          ??????????? 本來(lái)可以用#parameters.name[0]來(lái)獲得,請(qǐng)求中name的值。但是,在我實(shí)現(xiàn)include例子時(shí),
          ??????????? 無(wú)論我用param標(biāo)志給name賦任何值,#parameters里面不會(huì)含有任何值,所以#parameters.name也為空值。
          ????????????
          ??????????? 其原因?yàn)椋?
          ??????????? 當(dāng)使用include標(biāo)志時(shí),被包含的頁(yè)面(included)里#parameters拿到的是包含頁(yè)面里的請(qǐng)求參數(shù)。
          ????????????
          ??????????? 因此,這里必須手工調(diào)用request.getParameter("name")。
          ??????? -->
          ??? <s:iterator value="linkList" status="bean">
          ?? <tr>
          ??? <td class="data_tab_tdcl">
          ???? <s:property value="#bean.Index+1" />??? </td>
          ??? <td class="data_tab_tdcl"><s:property value="link_title" /></td>
          ??? <td class="data_tab_tdcl"><s:property value="link_url" /></td>
          ??? <td class="data_tab_tdcl">
          ??? <s:if test="link_type == 1">
          ?????????????????? 文字
          ??????????????? </s:if>
          ??????????????? <s:elseif test="link_type == 2">
          ?????????????????? 圖片
          ??????????????? </s:elseif>
          ???????????????? <s:else>
          ???????????????? -----
          ?????????????? </s:else>???
          ??? </td>

          ???
          ??? </body>
          </html>
          例1 condition.jsp
          iterator 描述:
          用于遍歷集合(java.util.Collection)或枚舉值(java.util.Iterator)。
          參數(shù):
          名稱(chēng)必需默認(rèn)類(lèi)型描述status否String如果設(shè)置此參數(shù),一個(gè)IteratorStatus的實(shí)例將會(huì)壓入每個(gè)遍歷的堆棧value否Object/String要遍歷的可枚舉的(iteratable)數(shù)據(jù)源,或者將放入新列表(List)的對(duì)象id否Object/String用來(lái)標(biāo)識(shí)元素的id。在UI和表單中為HTML的id屬性 例子:
          <%@ page c %>
          <%@ page import="java.util.List" %>
          <%@ page import="java.util.ArrayList" %>
          <%@ taglib prefix="s" uri="/struts-tags" %>

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <%
          ??? List list = new ArrayList();
          ??? list.add("Max");
          ??? list.add("Scott");
          ??? list.add("Jeffry");
          ??? list.add("Joe");
          ??? list.add("Kelvin");
          ??? request.setAttribute("names", list);
          %>
          <html>
          ??? <head>
          ??????? <title>Iterator</title>
          ??? </head>
          ??? <body>
          ??????? <h3>Names: </h3>
          ??????? <!--
          ??????????? 1、此處的空property元素用于獲得當(dāng)前iterator的值
          ??????????? 2、status被設(shè)成stuts,在iterator的里面就可以通過(guò)#stuts取得IteratorStatus的對(duì)象。IteratorStatus類(lèi)包含當(dāng)前序號(hào)信息,如是否第一個(gè)或最后一個(gè),是否為奇數(shù)序號(hào)。這些信息在我們做格式化的時(shí)候,顯得非常有用。
          ??????? -->
          ??????? <ol>
          ??????????? <s:iterator value="#request.names" status="stuts">????????????????
          ??????????????? <s:if test="#stuts.odd == true">
          ??????????????????? <li>White <s:property /></li>
          ??????????????? </s:if>
          ??????????????? <s:else>
          ??????????????????? <li style="background-color:gray"><s:property /></li>
          ??????????????? </s:else>
          ??????????? </s:iterator>
          ??????? </ol>
          ??? </body>
          </html>

          posted @ 2008-10-13 15:46 金家寶 閱讀(529) | 評(píng)論 (1)編輯 收藏

          Java筆試題(部分)

               摘要: EJB 方面 ? 94 、 EJB2.0 ...  閱讀全文

          posted @ 2008-10-09 11:56 金家寶 閱讀(724) | 評(píng)論 (0)編輯 收藏

          安裝WinCVS時(shí)Python不可用的問(wèn)題

          在我裝完Wincvs之后,提示我沒(méi)有安裝python,但后來(lái)我又裝了python2.4,可Wincvs還是說(shuō)配置不對(duì).到底要怎么配置python呢?期待著您的回復(fù),謝謝你了!
          ???
          TCL or Python are not available, shell is disabled。
          有的網(wǎng)友說(shuō)是版本的問(wèn)題,我今天安裝時(shí)也是一樣,裝了好三四個(gè)版本,都一樣,最后在CSDN上找到了答案。

          解決辦法:

          在admin-〉Preferences->wincvs中有關(guān)于python的設(shè)置, ?
          ? 其中python是指你的python虛擬機(jī)的位置,一般是python2X.dll的位置。在你來(lái)說(shuō)就是python24.dll的位置,一般這個(gè)文件會(huì)在你的系統(tǒng)文件中找到。 ?
          ? Tcl則一般會(huì)在python文件架的dlls子文件架中找到,一般名稱(chēng)為tclxx.dll,在你大概就是tcl84.dll。如果是安裝python2.3版本的話,會(huì)自動(dòng)找到,不需要設(shè)置。

          設(shè)置好了,WinCVS輸出窗口:

          Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32Tk is available, Tk-macros are enabledTCL is available, shell is enabled : help (select and press enter)

          posted @ 2008-09-21 08:52 金家寶 閱讀(3623) | 評(píng)論 (1)編輯 收藏

          [設(shè)計(jì)模式]jive中的[abstract Factory]

            AbstractFactory模式和可擴(kuò)展性
            假如要實(shí)現(xiàn)較好的可擴(kuò)展性,AbstractFactory模式確實(shí)是一件利器。如上面所說(shuō),假如要?jiǎng)?chuàng)建的Forum接口的不同實(shí)現(xiàn),而又不想更改代碼的話,就需要用到抽象工廠了。再Jive中,AuthorizationFactory類(lèi)是一個(gè)抽象類(lèi),用來(lái)創(chuàng)建Authorization對(duì)象。這是一個(gè)抽象工廠,可以通過(guò)不同的子類(lèi)來(lái)創(chuàng)建不同的Authorization對(duì)象。這個(gè)工廠的實(shí)現(xiàn)方法是:
            
            在AuthorizationFactory中使用一個(gè)private static變量factory,用來(lái)引用具體的抽象工廠的實(shí)例:
            private static AuthorizationFactory factory = null;
            
            用一個(gè)private static的String,來(lái)指明具體的抽象工廠的子類(lèi)類(lèi)名:
            private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";
            
            然后是用一個(gè)private static的loadAuthorizationFactory方法來(lái)給這個(gè)factory變量賦值,生成具體的抽象工廠類(lèi):
            
              private static void loadAuthorizationFactory() {
                if (factory == null) {
                  synchronized(className) {
                    if (factory == null) {
                      String classNameProp = PropertyManager.getProperty(
                        "AuthorizationFactory.className"
                      );
                      if (classNameProp != null) {
                        className = classNameProp;
                      }
                      try {
                        Class c = Class.forName(className);
                        factory = (AuthorizationFactory)c.newInstance();
                      }
                      catch (Exception e) {
                        System.err.println("Exception loading class: " + e);
                        e.printStackTrace();
                      }
                    }
                  }
                }
            }
            
            在static的getAuthorization方法返回一個(gè)Authorization的過(guò)程中,先初始化工廠類(lèi)factory變量,然后用factory的createAuthorization方法來(lái)創(chuàng)建:
            
              public static Authorization getAuthorization(String username,
                  String passWord) throws UnauthorizedException
              {
                loadAuthorizationFactory();
                return factory.createAuthorization(username, password);
            }
            
            不同的子類(lèi)有不同的createAuthorization方法的實(shí)現(xiàn)。比如在DbAuthorizationFactory這個(gè)AuthorizationFactory的數(shù)據(jù)庫(kù)實(shí)現(xiàn)子類(lèi)中,createAuthorization方法是這樣實(shí)現(xiàn)的:
            
              public Authorization createAuthorization(String username, String password)
                  throws UnauthorizedException
              {
                if (username == null password == null) {
                  throw new UnauthorizedException();
                }
                password = StringUtils.hash(password);
                int userID = 0;
                Connection con = null;
                PreparedStatement pstmt = null;
                try {
                  con = DbConnectionManager.getConnection();
                  pstmt = con.prepareStatement(AUTHORIZE);
                  pstmt.setString(1, username);
                  pstmt.setString(2, password);
            
                  ResultSet rs = pstmt.executeQuery();
                  if (!rs.next()) {
                    throw new UnauthorizedException();
                  }
                  userID = rs.getInt(1);
                }
                catch( SQLException sqle ) {
                  System.err.println("Exception in DbAuthorizationFactory:" + sqle);
                  sqle.printStackTrace();
                  throw new UnauthorizedException();
                }
                finally {
                  try { pstmt.close(); }
                  catch (Exception e) { e.printStackTrace(); }
                  try { con.close();  }
                  catch (Exception e) { e.printStackTrace(); }
                }
                return new DbAuthorization(userID);
              }
            
            在這個(gè)類(lèi)中,可以看到抽象類(lèi)和具體的子類(lèi)之間的關(guān)系,它們是如何協(xié)作的,又是如何劃分抽象方法和非抽象方法的,這都是值得注重的地方。一般的,抽象方法需要子類(lèi)來(lái)實(shí)現(xiàn),而抽象類(lèi)中的非抽象方法應(yīng)該所有子類(lèi)所能夠共享的,或者可是說(shuō),是定義在抽象方法之上的較高層的方法。這確實(shí)是一個(gè)抽象工廠的好例子!雖然實(shí)現(xiàn)的方法已經(jīng)和GOF中給出的實(shí)現(xiàn)相差較遠(yuǎn)了,但思想沒(méi)變,這兒的實(shí)現(xiàn),也確實(shí)是要巧妙的些。
            
            還有就是靜態(tài)方法的使用,使得這個(gè)類(lèi)看起來(lái)有些Singleton的意味。這使得對(duì)于AbstractFactory的創(chuàng)建變得簡(jiǎn)單。
            
            在AuthorizationFactory中定義的其它方法,涉及到具體的如何創(chuàng)建Authorization,都是作為abstract方法出現(xiàn),具體實(shí)現(xiàn)留給子類(lèi)來(lái)完成。
            
            這樣,在需要生成一個(gè)Authorization的時(shí)候,只需要調(diào)用AuthorizationFactory的靜態(tài)方法getAuthorization就可以了,由子類(lèi)實(shí)現(xiàn)了具體的細(xì)節(jié)。
            
            其它的,如同上面講到的,在創(chuàng)建Forum的時(shí)候用的ForumFactory,具有同上面一樣的實(shí)現(xiàn),這就是模式之所以稱(chēng)為模式的所在了。
          資料引用:http://www.knowsky.com/365144.html

          posted @ 2008-09-16 15:57 金家寶 閱讀(271) | 評(píng)論 (0)編輯 收藏

          題目: IOC 后臺(tái)機(jī)制學(xué)習(xí)

          ?
          題目: IOC 后臺(tái)機(jī)制學(xué)習(xí)
          給定:
          配置文件 config.txt, 文件內(nèi)容
          className = test.JavaBean1
          field = username
          value = ABC

          該文件中的三個(gè)值會(huì)隨時(shí)可能變化, 唯一不變的是 className 指定的都是一個(gè) JavaBean(為了簡(jiǎn)化, 我們假定里面已經(jīng)有一個(gè) username 屬性, 例如:

          class JavaBeanxxxx {
          ?? ?private String username;

          ?? ?public String getUsername() {
          ?? ??? ?return username;
          ?? ?}

          ?? ?public void setUsername(String uname) {
          ?? ??? ?this.username = uname;
          ?? ?}
          }

          要求: 寫(xiě)一段代碼, 讀取配置文件 config.txt, 然后實(shí)現(xiàn)把 className 指定的 JavaBean 類(lèi)加載(注意這個(gè)類(lèi)名是可以修改的, 可配置的), 然后生成一個(gè)實(shí)例,
          并把配置文件中field字段指定的值作為這個(gè)實(shí)例的屬性名(這里是username)所對(duì)應(yīng)的值設(shè)置為 ABC(字符串), 并且要讀出最后設(shè)置的值.

          此題已經(jīng)被 TigerTian 解答出來(lái), 歡迎學(xué)習(xí), 也感謝 TigerTian:
          package?com.gcoresoft.ioc;

          import?java.io.*;
          import?java.lang.reflect.*;
          import?java.util.*;
          import?java.beans.*;

          public?class?IOCStudy?{
          ????
          ????
          //Load?the?properties?file
          ????private?Properties?prop=new?Properties();
          ????
          ????
          public?void?loadPropFile(String?filename)
          ????{
          ????????
          try
          ????????{
          ????????????FileInputStream?fin
          =new?FileInputStream(filename);
          ????????????prop.load(fin);
          ????????????fin.close();
          ????????}
          catch(Exception?e){
          ????????????System.out.println(e.toString());
          ????????}
          ????}
          ????
          ????
          private?String?getValueByName(String?Name)
          ????{
          ????????
          return?prop.getProperty(Name);
          ????}
          ????
          ????
          public?static?void?main(String[]?args)
          ????{
          ????????IOCStudy?ioc
          =new?IOCStudy();
          ????????ioc.loadPropFile(
          "E:\\Work\\GetInIOC\\src\\com\\gcoresoft\\ioc\\Config.txt");
          ????????
          try
          ????????{
          ????????????Class?bean
          =Class.forName(ioc.getValueByName("className"));
          ????????????
          try?{
          ????????????????java.beans.BeanInfo?info
          =java.beans.Introspector.getBeanInfo(bean);
          ????????????????java.beans.PropertyDescriptor?pd[]
          =info.getPropertyDescriptors();
          ????????????????
          try?{
          ????????????????????Method?mSet
          =null,mRead=null;
          ????????????????????Object?obj
          =bean.newInstance();
          ????????????????????
          for(int?i=0;i<pd.length;i++)
          ????????????????????????
          if(pd[i].getName().equalsIgnoreCase(ioc.getValueByName("field")))
          ????????????????????????{
          ????????????????????????????mSet
          =pd[i].getWriteMethod();
          ????????????????????????????mRead
          =pd[i].getReadMethod();????????????????????????????
          ????????????????????????}
          ????????????????????
          try?{
          ????????????????????????mSet.invoke(obj,?ioc.getValueByName(
          "value"));
          ????????????????????????String?str
          =(String)mRead.invoke(obj,?null);
          ????????????????????????System.out.println(str);
          ????????????????????}?
          catch?(IllegalArgumentException?e)?{
          ????????????????????????
          //?TODO?Auto-generated?catch?block
          ????????????????????????e.printStackTrace();
          ????????????????????}?
          catch?(InvocationTargetException?e)?{
          ????????????????????????
          //?TODO?Auto-generated?catch?block
          ????????????????????????e.printStackTrace();
          ????????????????????}
          ????????????????}?
          catch?(InstantiationException?e)?{
          ????????????????????
          //?TODO?Auto-generated?catch?block
          ????????????????????e.printStackTrace();
          ????????????????}?
          catch?(IllegalAccessException?e)?{
          ????????????????????
          //?TODO?Auto-generated?catch?block
          ????????????????????e.printStackTrace();
          ????????????????}

          ????????????????
          ????????????}?
          catch?(IntrospectionException?e)?{
          ????????????????
          //?TODO?Auto-generated?catch?block
          ????????????????e.printStackTrace();
          ????????????}
          ????????????
          ????????????
          ????????}
          catch(ClassNotFoundException?e){
          ????????????System.out.println(e.toString());
          ????????}
          ????????
          ????}
          ????
          }

          posted @ 2008-08-27 20:41 金家寶 閱讀(300) | 評(píng)論 (0)編輯 收藏

          反向控制和面向切面編程在Spring的應(yīng)用

          引言

            在J2EE的整個(gè)發(fā)展歷程中,現(xiàn)在正是一個(gè)非常時(shí)刻。從很多方面來(lái)說(shuō),J2EE都是一個(gè)偉大的成功:它成功地在從前沒(méi)有標(biāo)準(zhǔn)的地方建立了標(biāo)準(zhǔn);大大提升了企業(yè)級(jí)軟件的開(kāi)放程度,并且得到了整個(gè)行業(yè)和開(kāi)發(fā)者的廣泛認(rèn)可。然而,J2EE在一些方面已經(jīng)開(kāi)始捉襟見(jiàn)肘。J2EE應(yīng)用開(kāi)發(fā)的成本通常很高。J2EE應(yīng)用項(xiàng)目至少和從前的非J2EE項(xiàng)目一樣容易失敗——如果不是更容易失敗的話。這樣的失敗率高得讓人難以接受。在這樣的失敗率之下,軟件開(kāi)發(fā)幾乎變成了碰運(yùn)氣。而在J2EE遭遇失敗的場(chǎng)景中,EJB通常都扮演著重要的角色。因此,J2EE社群不斷地向著更簡(jiǎn)單的解決方案、更少使用EJB的方向發(fā)展[1]。然而,每個(gè)應(yīng)用程序都需要一些基礎(chǔ)設(shè)施,拒絕使用EJB并不意味著拒絕EJB所采用的基礎(chǔ)設(shè)施解決方案。那么,如何利用現(xiàn)有的框架來(lái)提供這些基礎(chǔ)設(shè)施服務(wù)呢,伴隨著這個(gè)問(wèn)題的提出,一個(gè)輕量級(jí)的J2EE解決方案出現(xiàn)了,這就是Spring Framework。

            Spring是為簡(jiǎn)化企業(yè)級(jí)系統(tǒng)開(kāi)發(fā)而誕生的,Spring框架為J2EE應(yīng)用常見(jiàn)的問(wèn)題提供了簡(jiǎn)單、有效的解決方案,使用Spring,你可以用簡(jiǎn)單的POJO(Plain Old Java Object)來(lái)實(shí)現(xiàn)那些以前只有EJB才能實(shí)現(xiàn)的功能。這樣不只是能簡(jiǎn)化服務(wù)器端開(kāi)發(fā),任何Java系統(tǒng)開(kāi)發(fā)都能從Spring的簡(jiǎn)單、可測(cè)試和松耦合特征中受益??梢院?jiǎn)單的說(shuō),Spring是一個(gè)輕量級(jí)的反向控制(IoC)和面向切面編程(AOP)容器框架[3]。Spring IoC,借助于依賴注入設(shè)計(jì)模式,使得開(kāi)發(fā)者不用理會(huì)對(duì)象自身的生命周期及其關(guān)系,而且能夠改善開(kāi)發(fā)者對(duì)J2EE模式的使用;Spring AOP,借助于Spring實(shí)現(xiàn)的攔截器,開(kāi)發(fā)者能夠?qū)崿F(xiàn)以聲明的方式使用企業(yè)級(jí)服務(wù),比如安全性服務(wù)、事務(wù)服務(wù)等。Spring IoC和 Spring ; AOP組合,一起形成了Spring,這樣一個(gè)有機(jī)整體,使得構(gòu)建輕量級(jí)的J2EE架構(gòu)成為可能,而且事實(shí)證明,非常有效。沒(méi)有Spring IoC的Spring AOP是不完善的,沒(méi)有Spring AOP的Spring IoC是不健壯的。本文是以Spring架構(gòu)的成功的實(shí)際商務(wù)系統(tǒng)項(xiàng)目為背景,闡述了反向控制原理和面向切面的編程技術(shù)在Spring框架中的應(yīng)用,同時(shí)抽取適量代碼示意具體應(yīng)用,并和傳統(tǒng)開(kāi)發(fā)模式進(jìn)行對(duì)比,展示了Spring framework的簡(jiǎn)單,高效,可維護(hù)等優(yōu)點(diǎn)。

            1、Spring IoC 1.1 反向控制原理

            反向控制是Spring框架的核心。但是,反向控制是什么意思?到底控制的什么方面被反向了呢?2004年美國(guó)專(zhuān)家Martin Fowler發(fā)表了一篇論文《Inversion of Control Containers and the Dependency Injection pattern》闡述了這個(gè)問(wèn)題,他總結(jié)說(shuō)是獲得依賴對(duì)象的方式反向了,根據(jù)這個(gè)啟示,他還為反向控制提出了一個(gè)更貼切的名字:Dependency Injection(DI 依賴注入)。

            通常,應(yīng)用代碼需要告知容器或框架,讓它們找到自身所需要的類(lèi),然后再由應(yīng)用代碼創(chuàng)建待使用的對(duì)象實(shí)例。因此,應(yīng)用代碼在使用實(shí)例之前,需要?jiǎng)?chuàng)建對(duì)象實(shí)例。然而,IoC模式中,創(chuàng)建對(duì)象實(shí)例的任務(wù)交給IoC容器或框架(實(shí)現(xiàn)了IoC設(shè)計(jì)模式的框架也被稱(chēng)為IoC容器),使得應(yīng)用代碼只需要直接使用實(shí)例,這就是IoC。相對(duì)IoC 而言,“依賴注入”的確更加準(zhǔn)確的描述了這種設(shè)計(jì)理念。所謂依賴注入,即組件之間的依賴關(guān)系由容器在運(yùn)行期決定,形象的來(lái)說(shuō),即由容器動(dòng)態(tài)的將某種依賴關(guān)系注入到組件之中。

            1.2 IoC在Spring中的實(shí)現(xiàn)

            任何重要的系統(tǒng)都需要至少兩個(gè)相互合作的類(lèi)來(lái)完成業(yè)務(wù)邏輯。通常,每個(gè)對(duì)象都要自己負(fù)責(zé)得到它的合作(依賴)對(duì)象。你會(huì)發(fā)現(xiàn),這樣會(huì)導(dǎo)致代碼耦合度高而且難于測(cè)試。使用IoC,對(duì)象的依賴都是在對(duì)象創(chuàng)建時(shí)由負(fù)責(zé)協(xié)調(diào)系統(tǒng)中各個(gè)對(duì)象的外部實(shí)體提供的,這樣使軟件組件松散連接成為可能。下面示意了Spring IoC 應(yīng)用,步驟如下:

           ?。?)定義Action接口,并為其定義一個(gè)execute方法,以完成目標(biāo)邏輯。多年前,GoF在《Design Pattern:Elements of Reusable Object-Oriented Software》一書(shū)中提出“Programming to an Interface,not an implementation”的原則,這里首先將業(yè)務(wù)對(duì)象抽象成接口,正是為了實(shí)施這個(gè)原則。

           ?。?)類(lèi)UpperAction實(shí)現(xiàn)Action接口,在此類(lèi)中,定義一個(gè)String型的域message,并提供相應(yīng)的setter和getter方法,實(shí)現(xiàn)的execute方法如下:

          public String execute (String str) {
           return (getMessage () + str).toUpperCase () ;
          }

           ?。?)編寫(xiě)Spring配置文件(bean.xml)

          <beans>
          <bean id="TheAction" class="net.chen.spring.qs.UpperAction">
          <property name="message">
          <value>HeLLo</value>
          </property>
          </bean>
          </beans>

           ?。?)測(cè)試代碼

          public void testQuickStart () {
           ApplicationContext ctx=new
           FileSystemXmlApplicationContext ("bean.xml");
           Action a= (Action) ctx.getBean ("TheAction");
           System.out.println (a. execute ("Rod Johnson"));
          }

            上面的測(cè)試代碼中,我們根據(jù)"bean.xml"創(chuàng)建了一個(gè)ApplicationContext實(shí)例,并從此實(shí)例中獲取我們所需的Action實(shí)現(xiàn),運(yùn)行測(cè)試代碼,我們看到控制臺(tái)輸出:

          ……
          HELLO ROD JOHNSON

            仔細(xì)觀察一下上面的代碼,可以看到:

           ?。?)我們的組件并不需要實(shí)現(xiàn)框架指定的接口,因此可以輕松的將組件從Spring中脫離,甚至不需要任何修改,這在基于EJB框架實(shí)現(xiàn)的應(yīng)用中是難以想象的。

           ?。?)組件間的依賴關(guān)系減少,極大改善了代碼的可重用性。Spring的依賴注入機(jī)制,可以在運(yùn)行期為組件配置所需資源,而無(wú)需在編寫(xiě)組件代碼時(shí)就加以指定,從而在相當(dāng)程度上降低了組件之間的耦合。

            Spring給我們帶來(lái)了如此這般的好處,那么,反過(guò)來(lái),讓我們?cè)囅胍幌?,如果不使用Spring框架,回到我們傳統(tǒng)的編碼模式,情況會(huì)是怎樣呢?

            首先,我們必須編寫(xiě)一個(gè)配置文件讀取類(lèi),以實(shí)現(xiàn)Message屬性的可配置化。

            其次,得有一個(gè)Factory模式的實(shí)現(xiàn),并結(jié)合配置文件的讀寫(xiě)完成Action的動(dòng)態(tài)加載。于是,我們實(shí)現(xiàn)了一個(gè)ActionFactory來(lái)實(shí)現(xiàn)這個(gè)功能:

          public class ActionFactory {
           public static Action getAction (String actionName) {Properties pro = new Properties ();
           try {
            pro.load (new FileInputStream ("config.properties"));
            String actionImplName =(String)pro.get(actionName);
            String actionMessage =(String) pro.get (actionName+"_msg");
            Object obj =Class.forName (actionImplName).newInstance ();
            BeanUtils.setProperty(obj,"message",actionMessage);
            return (Action) obj;
           } catch (FileNotFoundException e) {
            ……
           }
          }

            配置文件則采用properties文件形式如下所示:

          TheAction=net.chen.spring.qs.UpperAction
          TheAction_msg=HeLLo

            測(cè)試代碼也作相應(yīng)修改?,F(xiàn)在不論實(shí)現(xiàn)的好壞,總之通過(guò)上面新增的多行代碼,終于實(shí)現(xiàn)了類(lèi)似的功能。如果現(xiàn)在有了一個(gè)新的需求,這樣這個(gè)ActionFactory每次都新建一個(gè)類(lèi)的實(shí)例,顯然這對(duì)系統(tǒng)性能不利,考慮到我們的兩個(gè)Action都是線程安全的,修改一下ActionFactory,保持系統(tǒng)中只有一個(gè)Action實(shí)例供其它線程調(diào)用。另外Action對(duì)象創(chuàng)建后,需要做一些初始化工作。修改一下ActionFactory,使其在創(chuàng)建Action實(shí)例之后,隨即就調(diào)用Action.init方法執(zhí)行初始化。Action的處理這樣就差不多了。下面我們來(lái)看看另外一個(gè)Factory

            ……

            往往這些系統(tǒng)開(kāi)發(fā)中最常見(jiàn)的需求,會(huì)導(dǎo)致我們的代碼迅速膨脹,而Spring IoC的出現(xiàn),則大大緩解了這樣的窘境。通過(guò)以上實(shí)例,可以看出,Spring IoC為我們提供了如下幾方面的優(yōu)勢(shì):

           ?。?)應(yīng)用組件不需要在運(yùn)行時(shí)尋找其協(xié)作者,因此更易于開(kāi)發(fā)和編寫(xiě)應(yīng)用;

            (2)由于借助于IoC容器管理組件的依賴關(guān)系,使得應(yīng)用的單元測(cè)試和集成測(cè)試更利于展開(kāi);

            (3)通常,在借助于IoC容器關(guān)系業(yè)務(wù)對(duì)象的前提下,很少需要使用具體IoC容器提供的API,這使得集成現(xiàn)有的遺留應(yīng)用成為可能。

            因此,通過(guò)使用IoC能夠降低組件之間的耦合度,最終,能夠提高類(lèi)的重用性,利于測(cè)試,而且更利于整個(gè)產(chǎn)品或系統(tǒng)集成和配置。
          2、Spring AOP

            2.1 面向切面編程基礎(chǔ)

            通常,系統(tǒng)由很多組件組成,每個(gè)組件負(fù)責(zé)一部分功能,然而,這些組件也經(jīng)常帶有一些除了核心功能之外的附帶功能 。系統(tǒng)服務(wù)如日志、事務(wù)管理和安全經(jīng)常融入到一些其他功能模塊中。這些系統(tǒng)服務(wù)通常叫做交叉業(yè)務(wù),這是因?yàn)樗鼈兛偸欠植荚谙到y(tǒng)的很多組件中。通過(guò)將這些業(yè)務(wù)分布在多個(gè)組件中,給我們的代碼引入了雙重復(fù)雜性。

            (1) 實(shí)現(xiàn)系統(tǒng)級(jí)業(yè)務(wù)的代碼在多個(gè)組件中復(fù)制。這意味著如果你要改變這些業(yè)務(wù)邏輯,你就必須到各個(gè)模塊去修改。就算把這些業(yè)務(wù)抽象成一個(gè)獨(dú)立模塊,其它模塊只是調(diào)用它的一個(gè)方法,但是這個(gè)方法調(diào)用也還是分布在很多地方。

            (2) 組件會(huì)因?yàn)槟切┡c自己核心業(yè)務(wù)無(wú)關(guān)的代碼變得雜亂。一個(gè)向地址錄中添加條目的方法應(yīng)該只關(guān)心如何添加地址,而不是關(guān)心它是不是安全或支持事務(wù)的。

            此時(shí),我們?cè)撛趺崔k呢?這正是AOP用得著的地方。AOP幫助我們將這些服務(wù)模塊化,并把它們聲明式地應(yīng)用在需要它們的地方,使得這些組件更加專(zhuān)注于自身業(yè)務(wù),完全不知道其它涉及到的系統(tǒng)服務(wù)。

            這里的概念切面,就是我們要實(shí)現(xiàn)的交叉功能,是應(yīng)用系統(tǒng)模塊化的一個(gè)方面或領(lǐng)域。切面的最常見(jiàn)例子就是日志記錄。日志記錄在系統(tǒng)中到處需要用到,利用繼承來(lái)重用日志模塊是不合適的,這樣,就可以創(chuàng)建一個(gè)日志記錄切面,并且使用AOP在系統(tǒng)中應(yīng)用。下圖展示了切面應(yīng)用方式


          圖表 1 應(yīng)用切面

            其中,通知Advice是切面的實(shí)際實(shí)現(xiàn)。連接點(diǎn)Joinpoint是應(yīng)用程序執(zhí)行過(guò)程中插入切面的地點(diǎn),這個(gè)地點(diǎn)可以是方法調(diào)用,異常拋出,甚至可以是要修改的字段,切面代碼在這些地方插入到你的應(yīng)用流程中,添加新的行為。切入點(diǎn)Pointcut定義了Advice應(yīng)該應(yīng)用在那些連接點(diǎn),通常通過(guò)指定類(lèi)名和方法名,或者匹配類(lèi)名和方法名式樣的正則表達(dá)式來(lái)指定切入點(diǎn)。

            2.2 AOP在Spring中的實(shí)現(xiàn)

            基于AOP,業(yè)界存在各種各樣的AOP實(shí)現(xiàn),比如,JBoss AOP、Spring AOP、AspectJ、Aspect Werkz等。各自實(shí)現(xiàn)的功能也不一樣。AOP實(shí)現(xiàn)的強(qiáng)弱在很大程度上取決于連接點(diǎn)模型。目前,Spring只支持方法級(jí)的連接點(diǎn)。這和一些其他AOP框架不一樣,如AspectJ和JBoss,它們還提供了屬性接入點(diǎn),這樣可以防止你創(chuàng)建特別細(xì)致的通知,如對(duì)更新對(duì)象屬性值進(jìn)行攔截。然而,由于Spring關(guān)注于提供一個(gè)實(shí)現(xiàn)J2EE服務(wù)的框架,所以方法攔截可以滿足大部分要求,而且Spring的觀點(diǎn)是屬性攔截破壞了封裝,讓Advice觸發(fā)在屬性值改變而不是方法調(diào)用上無(wú)疑是破壞了這個(gè)概念。

            Spring的AOP框架的關(guān)鍵點(diǎn)如下:

            (1)Spring實(shí)現(xiàn)了AOP聯(lián)盟接口。在Spring AOP中,存在如下幾種通知(Advice)類(lèi)型

            Before通知:在目標(biāo)方法被調(diào)用前調(diào)用,涉及接口org.springframework.aop.MethodBeforeAdvice;

            After通知:在目標(biāo)方法被調(diào)用后調(diào)用,涉及接口為org.springframework.aop.AfterReturningAdvice;

            Throws通知:目標(biāo)方法拋出異常時(shí)調(diào)用,涉及接口org.springframework.aop.MethodBeforeAdvice;

            Around通知:攔截對(duì)目標(biāo)對(duì)象方法調(diào)用,涉及接口為org.aopalliance.intercept.MethodInterceptor。

           ?。?)用java編寫(xiě)Spring通知,并在Spring的配置文件中,定義在什么地方應(yīng)用通知的切入點(diǎn)。

           ?。?)Spring的運(yùn)行時(shí)通知對(duì)象。代理Bean只有在第一次被應(yīng)用系統(tǒng)需要的時(shí)候才被創(chuàng)建。如果你使用的是ApplicationContext,代理對(duì)象在BeanFactory載入所有Bean的時(shí)候被創(chuàng)建。Spring有兩種代理創(chuàng)建方式。如果目標(biāo)對(duì)象實(shí)現(xiàn)了一個(gè)或多個(gè)接口暴露的方法,Spring將使用JDK的java.lang.reflect.Proxy類(lèi)創(chuàng)建代理。這個(gè)類(lèi)讓Spring動(dòng)態(tài)產(chǎn)生一個(gè)新的類(lèi),它實(shí)現(xiàn)所需的接口,織入了通知,并且代理對(duì)目標(biāo)對(duì)象的所有請(qǐng)求。如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)任何接口,Spring使用CGLIB庫(kù)生成目標(biāo)對(duì)象的子類(lèi)。在創(chuàng)建這個(gè)子類(lèi)的時(shí)候,Spring將通知織入,并且將對(duì)目標(biāo)對(duì)象的調(diào)用委托給這個(gè)子類(lèi)。此時(shí),需要將Spring發(fā)行包lib/cglib目錄下的JAR文件發(fā)布到應(yīng)用系統(tǒng)中。

            2.3 Spring AOP的優(yōu)勢(shì)

            借助于Spring AOP,Spring IoC能夠很方便的使用到非常健壯、靈活的企業(yè)級(jí)服務(wù),是因?yàn)镾pring AOP能夠提供如下幾方面的優(yōu)勢(shì):

           ?。?)允許開(kāi)發(fā)者使用聲明式企業(yè)服務(wù),比如事務(wù)服務(wù)、安全性服務(wù);EJB開(kāi)發(fā)者都知道,EJB組件能夠使用J2EE容器提供的聲明式服務(wù),但是這些服務(wù)要借助于EJB容器,而Spring AOP卻不需要EJB容器,借助于Spring的事務(wù)抽象框架就可以這些服務(wù)。

           ?。?)開(kāi)發(fā)者可以開(kāi)發(fā)滿足業(yè)務(wù)需求的自定義切面;

           ?。?)開(kāi)發(fā)Spring AOP Advice很方便。因?yàn)檫@些AOP Advice僅是POJO類(lèi),借助于Spring提供的ProxyFactoryBean,能夠快速的搭建Spring AOP Advice。

            3、結(jié)語(yǔ)

            本文詳細(xì)闡述了Spring背后的IoC原理和AOP技術(shù),以實(shí)際成功項(xiàng)目為背景,抽取簡(jiǎn)短片斷,展示了Spring架構(gòu)J2EE應(yīng)用系統(tǒng)的原理。Spring IoC借助于依賴注入機(jī)制,減輕了組件之間的依賴關(guān)系,同時(shí)也大大提高了組件的可移植性,組件得到了更多的重用機(jī)會(huì)。借助于Spring AOP,使得開(kāi)發(fā)者能聲明式、基于元數(shù)據(jù)訪問(wèn)企業(yè)級(jí)服務(wù),AOP合理補(bǔ)充了OOP技術(shù),Spring AOP合理地補(bǔ)充了Spring IoC容器。Spring IoC與Spring AOP組合,使得Spring成為成功的J2EE架構(gòu)框架,并能與標(biāo)準(zhǔn)的EJB等標(biāo)準(zhǔn)對(duì)抗,EJB不再是必需品。Spring已經(jīng)沖入了J2EE的核心,將引領(lǐng)整個(gè)J2EE開(kāi)發(fā)、架構(gòu)的方向。

          posted @ 2008-08-25 18:08 金家寶 閱讀(235) | 評(píng)論 (0)編輯 收藏

          GoF設(shè)計(jì)模式

          著名的EJB領(lǐng)域頂尖的專(zhuān)家Richard Monson-Haefel在其個(gè)人網(wǎng)站:www.EJBNow.com中極力推薦的GoF的《設(shè)計(jì)模式》,原文如下:

          Design Patterns
          Most developers claim to experience an epiphany reading this book. If you've never read the Design Patterns book then you have suffered a very serious gap in your programming education that should be remedied immediately.

          翻譯: 很多程序員在讀完這本書(shū),宣布自己相當(dāng)于經(jīng)歷了一次"主顯節(jié)"(紀(jì)念那穌降生和受洗的雙重節(jié)日),如果你從來(lái)沒(méi)有讀過(guò)這本書(shū),你會(huì)在你的程序教育生涯里存在一個(gè)嚴(yán)重裂溝,所以你應(yīng)該立即挽救彌補(bǔ)!

          可以這么說(shuō):GoF設(shè)計(jì)模式是程序員真正掌握面向?qū)ο蠛诵乃枷氲谋匦拚n。雖然你可能已經(jīng)通過(guò)了SUN的很多令人炫目的技術(shù)認(rèn)證,但是如果你沒(méi)有學(xué)習(xí)掌握GoF設(shè)計(jì)模式,只能說(shuō)明你還是一個(gè)技工。

          在瀏覽《Thingking in Java》(第一版)時(shí),你是不是覺(jué)得好象這還是一本Java基礎(chǔ)語(yǔ)言書(shū)籍?但又不純粹是,因?yàn)檫@本書(shū)的作者將面向?qū)ο蟮乃枷肭擅畹娜诤显贘ava的具體技術(shù)上,潛移默化的讓你感覺(jué)到了一種新的語(yǔ)言和新的思想方式的誕生。

          但是讀完這本書(shū),你對(duì)書(shū)中這些蘊(yùn)含的思想也許需要一種更明晰更系統(tǒng)更透徹的了解和掌握,那么你就需要研讀GoF的《設(shè)計(jì)模式》了。

          《Thingking in Java》(第一版中文)是這樣描述設(shè)計(jì)模式的:他在由Gamma, Helm和Johnson Vlissides簡(jiǎn)稱(chēng)Gang of Four(四人幫),縮寫(xiě)GoF編著的《Design Patterns》一書(shū)中被定義成一個(gè)“里程碑”。事實(shí)上,那本書(shū)現(xiàn)在已成為幾乎所有OOP(面向?qū)ο蟪绦蛟O(shè)計(jì))程序員都必備的參考書(shū)。(在國(guó)外是如此)。

          GoF的《設(shè)計(jì)模式》是所有面向?qū)ο笳Z(yǔ)言(C++ Java C#)的基礎(chǔ),只不過(guò)不同的語(yǔ)言將之實(shí)現(xiàn)得更方便地使用。

          GOF的設(shè)計(jì)模式是一座"橋"
          就Java語(yǔ)言體系來(lái)說(shuō),GOF的設(shè)計(jì)模式是Java基礎(chǔ)知識(shí)和J2EE框架知識(shí)之間一座隱性的"橋"。

          會(huì)Java的人越來(lái)越多,但是一直徘徊在語(yǔ)言層次的程序員不在少數(shù),真正掌握J(rèn)ava中接口或抽象類(lèi)的應(yīng)用不是很多,大家經(jīng)常以那些技術(shù)只適合大型項(xiàng)目為由,避開(kāi)或忽略它們,實(shí)際中,Java的接口或抽象類(lèi)是真正體現(xiàn)Java思想的核心所在,這些你都將在GoF的設(shè)計(jì)模式里領(lǐng)略到它們變幻無(wú)窮的魔力。

          GoF的設(shè)計(jì)模式表面上好象也是一種具體的"技術(shù)",而且新的設(shè)計(jì)模式不斷在出現(xiàn),設(shè)計(jì)模式自有其自己的發(fā)展軌道,而這些好象和J2EE .Net等技術(shù)也無(wú)關(guān)!

          實(shí)際上,GoF的設(shè)計(jì)模式并不是一種具體"技術(shù)",它講述的是思想,它不僅僅展示了接口或抽象類(lèi)在實(shí)際案例中的靈活應(yīng)用和智慧,讓你能夠真正掌握接口或抽象類(lèi)的應(yīng)用,從而在原來(lái)的Java語(yǔ)言基礎(chǔ)上躍進(jìn)一步,更重要的是,GoF的設(shè)計(jì)模式反復(fù)向你強(qiáng)調(diào)一個(gè)宗旨:要讓你的程序盡可能的可重用。

          這其實(shí)在向一個(gè)極限挑戰(zhàn):軟件需求變幻無(wú)窮,計(jì)劃沒(méi)有變化快,但是我們還是要尋找出不變的東西,并將它和變化的東西分離開(kāi)來(lái),這需要非常的智慧和經(jīng)驗(yàn)。

          而GoF的設(shè)計(jì)模式是在這方面開(kāi)始探索的一塊里程碑。

          J2EE等屬于一種框架軟件,什么是框架軟件?它不同于我們以前接觸的Java API等,那些屬于Toolkist(工具箱),它不再被動(dòng)的被使用,被調(diào)用,而是深刻的介入到一個(gè)領(lǐng)域中去,J2EE等框架軟件設(shè)計(jì)的目的是將一個(gè)領(lǐng)域中不變的東西先定義好,比如整體結(jié)構(gòu)和一些主要職責(zé)(如數(shù)據(jù)庫(kù)操作 事務(wù)跟蹤 安全等),剩余的就是變化的東西,針對(duì)這個(gè)領(lǐng)域中具體應(yīng)用產(chǎn)生的具體不同的變化需求,而這些變化東西就是J2EE程序員所要做的。

          由此可見(jiàn),設(shè)計(jì)模式和J2EE在思想和動(dòng)機(jī)上是一脈相承,只不過(guò)

          1.設(shè)計(jì)模式更抽象,J2EE是具體的產(chǎn)品代碼,我們可以接觸到,而設(shè)計(jì)模式在對(duì)每個(gè)應(yīng)用時(shí)才會(huì)產(chǎn)生具體代碼。

          2.設(shè)計(jì)模式是比J2EE等框架軟件更小的體系結(jié)構(gòu),J2EE中許多具體程序都是應(yīng)用設(shè)計(jì)模式來(lái)完成的,當(dāng)你深入到J2EE的內(nèi)部代碼研究時(shí),這點(diǎn)尤其明顯,因此,如果你不具備設(shè)計(jì)模式的基礎(chǔ)知識(shí)(GoF的設(shè)計(jì)模式),你很難快速的理解J2EE。不能理解J2EE,如何能靈活應(yīng)用?

          3.J2EE只是適合企業(yè)計(jì)算應(yīng)用的框架軟件,但是GoF的設(shè)計(jì)模式幾乎可以用于任何應(yīng)用!因此GoF的設(shè)計(jì)模式應(yīng)該是J2EE的重要理論基礎(chǔ)之一。

          所以說(shuō),GoF的設(shè)計(jì)模式是Java基礎(chǔ)知識(shí)和J2EE框架知識(shí)之間一座隱性的"橋"。為什么說(shuō)隱性的?

          GOF的設(shè)計(jì)模式是一座隱性的"橋"
          因?yàn)楹芏嗳藳](méi)有注意到這點(diǎn),學(xué)完Java基礎(chǔ)語(yǔ)言就直接去學(xué)J2EE,有的甚至鴨子趕架,直接使用起Weblogic等具體J2EE軟件,一段時(shí)間下來(lái),發(fā)現(xiàn)不過(guò)如此,挺簡(jiǎn)單好用,但是你真正理解J2EE了嗎?你在具體案例中的應(yīng)用是否也是在延伸J2EE的思想?

          如果你不能很好的延伸J2EE的思想,那你豈非是大炮轟蚊子,認(rèn)識(shí)到J2EE不是適合所有場(chǎng)合的人至少是明智的,但我們更需要將J2EE用對(duì)地方,那么只有理解J2EE此類(lèi)框架軟件的精髓,那么你才能真正靈活應(yīng)用Java解決你的問(wèn)題,甚至構(gòu)架出你自己企業(yè)的框架來(lái)。(我們不能總是使用別人設(shè)定好的框架,為什么不能有我們自己的框架?)

          因此,首先你必須掌握GoF的設(shè)計(jì)模式。雖然它是隱性,但不是可以越過(guò)的。

          ?

          關(guān)于本站“設(shè)計(jì)模式”

          Java提供了豐富的API,同時(shí)又有強(qiáng)大的數(shù)據(jù)庫(kù)系統(tǒng)作底層支持,那么我們的編程似乎變成了類(lèi)似積木的簡(jiǎn)單"拼湊"和調(diào)用,甚至有人提倡"藍(lán)領(lǐng)程序員",這些都是對(duì)現(xiàn)代編程技術(shù)的不了解所至.

          在真正可復(fù)用的面向?qū)ο缶幊讨?GoF的《設(shè)計(jì)模式》為我們提供了一套可復(fù)用的面向?qū)ο蠹夹g(shù),再配合Refactoring(重構(gòu)方法),所以很少存在簡(jiǎn)單重復(fù)的工作,加上Java代碼的精煉性和面向?qū)ο蠹儩嵭?設(shè)計(jì)模式是java的靈魂),編程工作將變成一個(gè)讓你時(shí)刻體驗(yàn)創(chuàng)造快感的激動(dòng)人心的過(guò)程.

          為能和大家能共同探討"設(shè)計(jì)模式",我將自己在學(xué)習(xí)中的心得寫(xiě)下來(lái),只是想幫助更多人更容易理解GoF的《設(shè)計(jì)模式》。由于原著都是以C++為例, 以Java為例的設(shè)計(jì)模式基本又都以圖形應(yīng)用為例,而我們更關(guān)心Java在中間件等服務(wù)器方面的應(yīng)用,因此,本站所有實(shí)例都是非圖形應(yīng)用,并且順帶剖析Jive論壇系統(tǒng).同時(shí)為降低理解難度,盡量避免使用UML圖.

          如果你有一定的面向?qū)ο缶幊探?jīng)驗(yàn),你會(huì)發(fā)現(xiàn)其中某些設(shè)計(jì)模式你已經(jīng)無(wú)意識(shí)的使用過(guò)了;如果你是一個(gè)新手,那么從開(kāi)始就培養(yǎng)自己良好的編程習(xí)慣(讓你的的程序使用通用的模式,便于他人理解;讓你自己減少重復(fù)性的編程工作),這無(wú)疑是成為一個(gè)優(yōu)秀程序員的必備條件.

          整個(gè)設(shè)計(jì)模式貫穿一個(gè)原理:面對(duì)接口編程,而不是面對(duì)實(shí)現(xiàn).目標(biāo)原則是:降低耦合,增強(qiáng)靈活性.

          posted @ 2008-07-07 11:05 金家寶 閱讀(280) | 評(píng)論 (0)編輯 收藏

          什么是MIS

          所謂MIS(管理信息系統(tǒng)--Management Information System)系統(tǒng),是一個(gè)由人、計(jì)算機(jī)及其他外圍設(shè)備等組成的能進(jìn)行信息的收集、傳遞、存貯、加工、維護(hù)和使用的系統(tǒng)。它是一門(mén)新興的科學(xué),其主要任務(wù)是最大限度的利用現(xiàn)代計(jì)算機(jī)及網(wǎng)絡(luò)通訊技術(shù)加強(qiáng)企業(yè)的信息管理,通過(guò)對(duì)企業(yè)擁有的人力、物力、財(cái)力、設(shè)備、技術(shù)等資源的調(diào)查了解,建立正確的數(shù)據(jù),加工處理并編制成各種信息資料及時(shí)提供給管理人員,以便進(jìn)行正確的決策,不斷提高企業(yè)的管理水平和經(jīng)濟(jì)效益。目前,企業(yè)的計(jì)算機(jī)網(wǎng)絡(luò)已成為企業(yè)進(jìn)行技術(shù)改造及提高企業(yè)管理水平的重要手段。隨著我國(guó)與世界信息高速公路的接軌,企業(yè)通過(guò)計(jì)算機(jī)網(wǎng)絡(luò)獲得信息必將為企業(yè)帶來(lái)巨大的經(jīng)濟(jì)效益和社會(huì)效益,企業(yè)的辦公及管理都將朝著高效、快速、無(wú)紙化的方向發(fā)展。MIS系統(tǒng)通常用于系統(tǒng)決策,例如,可以利用MIS系統(tǒng)找出目前迫切需要解決的問(wèn)題,并將信息及時(shí)反饋給上層管理人員,使他們了解當(dāng)前工作發(fā)展的進(jìn)展或不足。換句話說(shuō),MIS系統(tǒng)的最終目的是使管理人員及時(shí)了解公司現(xiàn)狀,把握將來(lái)的發(fā)展路徑。

            一個(gè)完整的MIS應(yīng)包括:輔助決策系統(tǒng)(DSS)、工業(yè)控制系統(tǒng)(IPC)、辦公自動(dòng)化系統(tǒng)(OA)以及數(shù)據(jù)庫(kù)、模型庫(kù)、方法庫(kù)、知識(shí)庫(kù)和與上級(jí)機(jī)關(guān)及外界交換信息的接口。其中,特別是辦公自動(dòng)化系統(tǒng)(OA)、與上級(jí)機(jī)關(guān)及外界交換信息等都離不開(kāi)Intranet的應(yīng)用。可以這樣說(shuō),現(xiàn)代企業(yè)MIS不能沒(méi)有 Intranet,但I(xiàn)ntranet的建立又必須依賴于MIS的體系結(jié)構(gòu)和軟硬件環(huán)境。

            傳統(tǒng)的MIS系統(tǒng)的核心是CS (Client/Server——客戶端/服務(wù)器)架構(gòu),而基于Internet的MIS系統(tǒng)的核心是BS(Browser/Server——瀏覽器/服務(wù)器)架構(gòu)。BS架構(gòu)比起CS架構(gòu)有著很大的優(yōu)越性,傳統(tǒng)的MIS系統(tǒng)依賴于專(zhuān)門(mén)的操作環(huán)境,這意味著操作者的活動(dòng)空間受到極大限制;而B(niǎo)S架構(gòu)則不需要專(zhuān)門(mén)的操作環(huán)境,在任何地方,只要能上網(wǎng),就能夠操作MIS系統(tǒng),這其中的優(yōu)劣差別是不言而喻的。

            基于Internet上的 MIS系統(tǒng)是對(duì)傳統(tǒng)MIS系統(tǒng)概念上的擴(kuò)展,它不僅可以用于高層決策,而且可以用于進(jìn)行普通的商務(wù)管理。通過(guò)用戶的具名登錄(或匿名登錄),以及相應(yīng)的權(quán)限控制,可以實(shí)現(xiàn)在遠(yuǎn)端對(duì)系統(tǒng)的瀏覽、查詢、控制和審閱。隨著Internet的擴(kuò)展,現(xiàn)有的公司和學(xué)校不再局限于物理的有形的真實(shí)的地域,網(wǎng)絡(luò)本身成為事實(shí)上發(fā)展的空間?;贗nternet上的MIS系統(tǒng),彌補(bǔ)了傳統(tǒng)MIS系統(tǒng)的不足,充分體現(xiàn)了現(xiàn)代網(wǎng)絡(luò)時(shí)代的特點(diǎn)。隨著Internet技術(shù)的高速發(fā)展,因特網(wǎng)必將成為人類(lèi)新社會(huì)的技術(shù)基石?;贗nternet的MIS系統(tǒng)必將成為網(wǎng)絡(luò)時(shí)代的新一代管理信息系統(tǒng),前景極為樂(lè)觀

          posted @ 2008-07-05 19:20 金家寶 閱讀(222) | 評(píng)論 (0)編輯 收藏

          開(kāi)發(fā)者版本:你屬于哪個(gè)版本的程序員?

          國(guó)外開(kāi)發(fā)者博客中有一篇有趣的文章,將程序員按水平像軟件版本號(hào)那樣劃分為不同的版本。相對(duì)于在招聘時(shí)分為初級(jí),中級(jí),高級(jí)程序員,直接表明需要某種語(yǔ)言N版本的程序員或許更方便直接。根據(jù)作者的觀點(diǎn),可將WEB開(kāi)發(fā)者大致分為以下幾個(gè)版本:

          Alpha:閱讀過(guò)一些專(zhuān)業(yè)書(shū)籍,大多數(shù)能用Dreamweaver或者FrontPage幫朋友制作一些Web頁(yè)面。但在他們熟練掌握HTML代碼以前,你大概不會(huì)雇傭他們成為職業(yè)的WEB制作人員。

          Beta:已經(jīng)比較擅長(zhǎng)整合站點(diǎn)頁(yè)面了,在HTML技巧方面也有一定造詣,但還是用Tables來(lái)制作頁(yè)面,不了解CSS,在面對(duì)動(dòng)態(tài)頁(yè)面或數(shù)據(jù)庫(kù)連接時(shí)還是底氣不足。

          Pre Version 1 (0.1):比Beta版的開(kāi)發(fā)者水平要高。熟悉HTML,開(kāi)始了解CSS是如何運(yùn)作的,懂一點(diǎn)JavaScript,但還是基于業(yè)余水準(zhǔn),逐步開(kāi)始關(guān)心動(dòng)態(tài)站點(diǎn)搭建和數(shù)據(jù)庫(kù)連接的知識(shí)。這個(gè)版本的WEB開(kāi)發(fā)人員還遠(yuǎn)不能成為雇主眼中的香餑餑。

          1.0: 能夠基本把控整個(gè)站點(diǎn)開(kāi)發(fā),針對(duì)每個(gè)問(wèn)題盡可能的找到最直接的解決辦法。但對(duì)可測(cè)性,可擴(kuò)展性以及在不同(層)框架下如何選擇最合適的WEB設(shè)計(jì)工具尚無(wú)概念。這個(gè)版本的WEB開(kāi)發(fā)者有良好的技術(shù)基礎(chǔ),需要有進(jìn)一步的幫助和指導(dǎo)。



          2.0:懂面向?qū)ο蟮木幊陶Z(yǔ)言,理解分層開(kāi)發(fā)的必要性,關(guān)注代碼分離,對(duì)問(wèn)題尋找更完美的解決方法,偶然也會(huì)考慮設(shè)計(jì)模式的問(wèn)題,但對(duì)此仍然概念不清。屬于優(yōu)秀的初級(jí)開(kāi)發(fā)者,能完成較松散的代碼開(kāi)發(fā)(相對(duì)大型嚴(yán)謹(jǐn)?shù)恼军c(diǎn)開(kāi)發(fā)而言),在面對(duì)較復(fù)雜問(wèn)題尋找解決辦法時(shí)需要周邊人的幫助。

          3.0:開(kāi)始較為深入的理解面向?qū)ο缶幊毯驮O(shè)計(jì)模式,了解他們的用途,當(dāng)看到好的設(shè)計(jì)模式時(shí)能看透其本質(zhì),逐步關(guān)注分層的架構(gòu)解決辦法和可測(cè)試性。理解不同的開(kāi)發(fā)語(yǔ)言并能說(shuō)出他們的異同(例如各自的優(yōu)勢(shì))。屬于優(yōu)秀的中級(jí)別開(kāi)發(fā)者,雇主也確信他們最終能找到問(wèn)題的解決辦法,這個(gè)版本的人可以給1.0和2.0的開(kāi)發(fā)者以指導(dǎo)。但他們對(duì)架構(gòu)的理解仍然不夠清晰,值得一提的是,只要給予一些指導(dǎo),他們能很快理解并熟記做出的決定,以及選定方案的優(yōu)勢(shì)所在。

          4.0:
          理解模式,重視用戶的反饋。著手研究方法論,架構(gòu)設(shè)計(jì)和軟件開(kāi)發(fā)的最佳入口。頭腦中已經(jīng)形成了超越開(kāi)發(fā)語(yǔ)言,技術(shù)架構(gòu)的整體方案,可根據(jù)需求解構(gòu)程序。能從理論的角度,不同模式如何融合成最佳形態(tài),將多種X-驅(qū)動(dòng)的模式應(yīng)用到不同的方案中。是精通多語(yǔ)言的高手,理解不同系統(tǒng)和方法論的細(xì)微差別,屬于高級(jí)程序員。這個(gè)級(jí)別的人能夠輕易的輔導(dǎo)2.0和3.0的程序員,將他們推向更高的級(jí)別。

          5.0:從系統(tǒng)的角度考慮問(wèn)題。對(duì)各種系統(tǒng)結(jié)構(gòu)有深入研究,能對(duì)整個(gè)代碼架構(gòu)中的問(wèn)題進(jìn)行改進(jìn)。在團(tuán)隊(duì)粘合性以及代碼安全性方面有杰出貢獻(xiàn)。對(duì)1.0到4.0版本的開(kāi)發(fā)人員出現(xiàn)的問(wèn)題能及時(shí)察覺(jué),讓整個(gè)團(tuán)隊(duì)保持積極性且保持興奮的狀態(tài)創(chuàng)建軟件解決辦法。舉例來(lái)說(shuō),他們總是對(duì)新的技術(shù)和信息保持饑渴狀態(tài),試圖用最簡(jiǎn)便的方案解決開(kāi)發(fā)任務(wù)。在整個(gè)IT團(tuán)隊(duì)中獲得信任,屬于高級(jí)程序員和架構(gòu)師。

          那么,您屬于哪個(gè)版本的程序員呢?

          posted @ 2008-06-27 10:47 金家寶 閱讀(247) | 評(píng)論 (0)編輯 收藏

          Eclipse官方網(wǎng)站已經(jīng)正式宣布 Eclipse 3.4發(fā)布

          感謝Wendal,匿名人士的投遞
          Eclipse官方網(wǎng)站已經(jīng)正式宣布 Eclipse 3.4發(fā)布,代號(hào)為ganymede (Ganymede (英語(yǔ)發(fā)音"GAN uh meed")為最大的木星已知衛(wèi)星,也是第七顆發(fā)現(xiàn)的木星衛(wèi)星,在伽利略發(fā)現(xiàn)的衛(wèi)星中離木星第三近,在希臘神話中 Ganymede是一個(gè)特洛伊美人的男孩(一個(gè)美少男),被宙斯帶去給眾神斟酒)。

          ?

          關(guān)注Eclipse項(xiàng)目的開(kāi)發(fā)者朋友們可以下載3.4版本嘗試一下,在JavaEye上還專(zhuān)門(mén)介紹一個(gè)很酷的Eclipse3.4帶的實(shí)時(shí)結(jié)對(duì)編程插件

          目前3.4版本是Eclipse項(xiàng)目發(fā)布的10周年慶典版;至今Eclipse項(xiàng)目共有23個(gè)子項(xiàng)目。此次發(fā)布的Ganymede 版本引入不少亮點(diǎn),其中包括新的p2平臺(tái)(provisioning platform),點(diǎn)擊查看p2的介紹、新增的Equinox(OSGi實(shí)現(xiàn))安全方面的特性、全新的Ecore建模工具、支持SOA等。

          posted @ 2008-06-26 09:01 金家寶 閱讀(816) | 評(píng)論 (1)編輯 收藏

          主站蜘蛛池模板: 孟村| 富民县| 左贡县| 徐汇区| 焉耆| 新民市| 锡林浩特市| 东乌珠穆沁旗| 清流县| 宜宾县| 同仁县| 丰台区| 潜山县| 鹿邑县| 龙口市| 湖口县| 梁河县| 石棉县| 天峻县| 白河县| 宁远县| 古田县| 寿阳县| 山阳县| 鄂州市| 辛集市| 南川市| 临江市| 邛崃市| 西盟| 岑溪市| 外汇| 图们市| 千阳县| 上高县| 桐柏县| 叶城县| 应用必备| 龙川县| 重庆市| 叙永县|