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

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

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

    爪哇東南的自留地

    學習探討開源和web開發

    導航

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    相冊

    收藏夾

    life

    technique

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    2006年10月2日 #

    數碼攝影中的光及用光技巧

         摘要: 大家都知道,攝影是光的藝術!沒有光線,就沒有攝影;用光不當,就得不到一幅滿意的照片。因此,光是攝影的基礎,有了它,感光材料才有感光的可能;有了它,物體才能顯現出形態、色彩和質感。 ??? 布光,則是攝影中的一項創造性工作,它體現著一個攝影師的個性和風格,也關系到一幅作品的成敗。 ??? 從某種意義上講,不管是攝...  閱讀全文

    posted @ 2006-10-02 14:32 ericli 閱讀(1550) | 評論 (2)編輯 收藏

    2006年9月27日 #

    數碼攝影入門之六 名家名言

    根據
    美國攝影家維利·奎克的看法,幾乎所有的人都能夠通過應用一些基本法則,達到具有相當水平的攝影構圖能力。為此,他提出了一些簡單的方法。他認為,依據這些方法,任何人都能在短時間內學會拍出較好的照片。

    有些人或許對構圖有天賦。不過,根據美國攝影家維利·奎克的看法,幾乎所有的人都能夠通過應用一些基本法則,達到具有相當水平的攝影構圖能力。為此,他提出了一些簡單的方法。他認為,依據這些方法,任何人都能在短時間內學會拍出較好的照片。?

    維利·奎克指出,攝影者最易犯的錯誤是拍攝點取得過高,與被攝體離得太遠,致使畫面出現各種各樣與拍攝目的毫無關系的東西。

    他說:“請記住,畫家是 把東西畫進畫面,而攝影者則是從畫面去掉一些東西。” 他說:“一張照片應該只有一個趣味中心,畫面上不能有無用的東西。如果你對某個物體是否有助于畫面抱有懷疑,你就應盡可能地把它放棄掉。” 這里就是人們常說的攝影是“減法的藝術”

    奎克認為:“這并不是說,趣味中心非得準確地置于交叉點上不可。正因為如此,實際上趣味中心常出現在交叉點附近。”?

    奎克指出:“每一幅照片都應保持一定的平衡。這就是說,對主要被攝體的安排,不能使畫、面出現向分量大的一邊傾倒。但平衡并不意味著將兩個同樣大小和同等形狀的東西置于對稱的位置。這里的關系,只要你看一下在玩蹺蹺板的孩子就知道了。蹺蹺板兩邊的孩子,小些的一個必定坐在離中央遠些的地方,而大的孩子肯定坐在靠近中央的地方。”?

    奎克認為:“把突出的線條安排,指向趣味中心,是拍攝一幅悅目照片的另一個要素。這些線條被稱為主導線,有效地利用主導線,可以創造出驚人的照片。把主導線安排成對角線,會產生有力的動感。?

    “線條常常在照片中提供一個邊框。這可以通過選擇視點來進行,例如在樹下通過樹枝框住畫面上的被攝主體。此時通常使用小光圈,以使整幅照片清晰。這樣做,也有可能使邊框過于突出,但安排適當,會得到好照片。?
    “在一幅照片中,地平線的位置會給人以強烈的印象。拍攝時,地平線要盡量避免處在照片的等比線上,因為這樣做會把照片均分為兩半,給人以呆板的感覺。?

    地平線處在畫面下方,會給人以寧靜的感覺,而處于上方,給人的感覺則是活潑、有力的。 “此外,橫幅畫面可以產生安寧、平靜的感覺,而豎直畫面則會產生動態效果。”?

    奎克認為,以上方法如果運用得好,你的照片將會出現明顯的改觀,而且隨著時間的推移,你很快就會學會鑒賞構圖,從而為你增添攝影的樂趣。?

    達柯 認為,有時“如果線條與視覺產生了共鳴,一簇線條本身就能成為一個主體”。

    美國攝影家L.小雅各希斯認為:“構圖是從攝影者的心靈的眼睛做起的。構圖的過程也被稱為‘預見’,就是在未拍攝某一物體之前或正在拍攝的時候,就能在腦海中形成一個圖像或印象。通過經常析自己和別人的作品的構圖,就會使自己的這種預見本領更加嫻熟,變成一種本能。”這就是我常說的用腦子拍照。

    線條構成畫面

    奧地利攝影家伊涅斯特·哈斯對此也有同感,對于構圖,他己達到手中無劍,劍在心中的境界,他認為、“構圖在于平衡,每個人對平衡的處理都各有不同。”正如同武功達到最高境界時,已沒有招式名稱,只憑自己的功力去化解。他認為:“你越能忘記你的器材,就越能集中你的題材和構圖,這時相機只是你眼睛的延續,再沒有其他意義。” 小雅各布斯還認為:“構圖的最基本的因素是線條、形式、質感以及這些因素之間的空間。當然色彩同樣也是不可忽略的因素。會聚的線條一般能說明透視關系,但并不是所有的照片都非要表現出透視的深度不可。許多杰出的作品都是平面圖案。在取景器中的某個景物或人物的肖像,都是根據攝影者個人的感受進行安排的。就是所謂攝影里所有的控制是服務于你想表達的情緒。

    色彩的平衡很重要

    “在大多數情況下,每幅照片中都有一個或一組形狀或形式起主導作用,而照片中的色彩、體積、位置和其他形狀等,都是為主導因素服務的。……構圖中的對比,是指大與小、明與暗、近與遠、主動與被動、平滑與粗糙、色彩的濃艷與輕淡等等的對比。要多利用這些相互對立的因素,通過它門使主體影響整個構圖。例如,恰當地利用對比法則,照片就會具有強大的魅力。”?

    攝影家瓦爾特·德·格魯伊特對攝影構圖作闡述。他認為:“每一種構圖都是以排列次序為基礎的,就像我們從哥士達心理學和信息學原理中所了解到的那樣,構圖可以用多種方法獲得。它產生于相似事物的組合以及對相反事物的強調。排列次序并不是千篇一律的,形態和色彩的疏密和對比也會產生排列次序。排列次序是以一種美學上的均衡為基礎的,而均衡則從復雜、矛盾和動態之中造就和諧。”

    線條的引導作用,所有的線條匯聚到中心主體

    他說:“任何人,只要懂得把照片分成單個的構圖成分,借以得出它在美學上的一致性和合理性來審查照片的具體效果,就都會成功地創作出好的作品。"?

    "要獲得令人滿意的照片構圖,須經常分析照片。” 他提出的分析照片構圖的最重要標準是:?

    1.人物和環境的關系以及反差情況。 2.照片所傳遞的信息的價值以及類似事物。 3.照明和縱深。4.突出的線條和照片的畫幅。

    對于如何獲得較好的攝影構圖,格魯伊特提出了以下重要建議:

    a.畫面所提供的信息不能造成視覺上的混亂。?

    b.人物和環境的關系要有助于傳達照片的意圖。?

    c.應當避免由于人物和環境之間的含糊關系而可能產生的錯覺。

    d.明與暗的關系或者彩色對比的關系是非常重要的。?

    e.除了人物和環境在形式上的關系之外,對人物和環境的心理上的權衡也是 十分重要的,因為每個視覺印象都立即作出喜歡或不喜歡的判斷。無偏好的估價意味著根本沒有反應。?

    茉莉mm的“光繪”

    f.表現與我們熟悉的物體相類似的東西,使人容易辨認,從而能比較迅速地予以理解。因此,重復內容是必要的。

    g.照片的復雜程度一定不能太低(感官刺激不夠),也不能太高(感官刺激過分)?

    h.每個人對每幅照片的美學評價總是不一樣的,而且這種評價是受感情支配的。它在很大程度上取決于觀眾的認識,他的經歷和他的敏感性。?

    i.形式主義和時髦風尚是不能持久的。這種缺乏獨創性的缺點,是不可能用技術補償的。?

    j.照明、透視、重疊和影紋的層次變化,有助于在二維空間的平面上體現出明顯的縱深感。

    k.不尋常的透視效果,有助于使照片生動活潑。?

    l.有意識地使用突出的方向線和選擇適合主體的畫幅,會加強照片的效果。

    更多名家名言和作者發表的個人看法,請訪問:

    posted @ 2006-09-27 13:49 ericli 閱讀(264) | 評論 (0)編輯 收藏

    2006年9月25日 #

    一些攝影方面的術語

    CCD:
    中文譯為"電子耦合組件"(charged coupled device),它就像傳統相機的底片一樣,是感應光線的電路裝置,可以將它想象成一顆顆微小的感應粒子,鋪滿在光學鏡頭后方,當光線與圖像從鏡頭透過、投射到ccd表面時,ccd就會產生電流,將感應到的內容轉換成數碼資料儲存起來。ccd的尺寸其實是說感光器件的面積大小,ccd像素數目越多、單一像素尺寸越大,捕獲的光子越多,感光性能越好,信噪比越低,收集到的圖像就會越清晰。因此,盡管ccd數目并不是決定圖像品質的唯一重點,我們仍然可以把它當成相機等級的重要判準之一。

    CMOS:?
    互補性氧化金屬半導體CMOS(Complementary Metal-Oxide Semiconductor)和CCD一樣同為在數碼相機中可記錄光線變化的半導體。CMOS的制造技術和一般計算機芯片沒什么差別,主要是利用硅和鍺這兩種元素所做成的半導體,使其在CMOS上共存著帶N(帶–電) 和 P(帶+電)級的半導體,這兩個互補效應所產生的電流即可被處理芯片紀錄和解讀成影像。同樣,CMOS的尺寸大小影響感光性能的效果,面積越大感光性能越好。CMOS的缺點就是太容易出現雜點, 這主要是因為早期的設計使CMOS在處理快速變化的影像時,由于電流變化過于頻繁而會產生過熱的現象。
    光學變焦倍數:光學變焦是依靠光學鏡頭結構來實現變焦,變焦方式與35mm相機差不多,就是通過攝像頭的鏡片移動來放大與縮小需要拍攝的景物,光學變焦倍數越大,能拍攝的景物就越遠。如今的數碼相機的光學變焦倍數大多在2倍-5倍之間,也有一些碼相機擁有10倍的光學變焦效果。而家用攝像機的光學變焦倍數在10倍-25倍,能比較清楚地拍到70米外的東西。

    光圈:
    光圈英文名稱為Aperture,光圈是一個用來控制光線透過鏡頭,進入機身內感光面的光量的裝置,也是相機一個極其重要的指標參數,它通常是在鏡頭內。它的大小決定著通過鏡頭進入感光元件的光線的多少。表達光圈大小我們是用F值。光圈F值 = 鏡頭的焦距 / 鏡頭口徑的直徑從以上的公式可知要達到相同的光圈F值,長焦距鏡頭的口徑要比短焦距鏡頭的口徑大。

    ????我們平時所說的光圈值F2.8、F8、F16等是光圈“系數”,是相對光圈,并非光圈的物理孔徑,與光圈的物理孔徑及鏡頭到感光器件(膠片或CCD或CMOS)的距離有關。

    ????當光圈物理孔徑不變時,鏡頭中心與感光器件距離愈遠,F數愈小,反之,鏡頭中心與感光器件距離愈近,通過光孔到達感光器件的光密度愈高,F數就愈大。完整的光圈值系列如下: F1, F1.4, F2, F2.8, F4, F5.6, F8, F11, F16, F22, F32, F44, F64。

    噪點:
    噪點產生的原因:

    1、長時間曝光產生的圖像噪音

    ????這種現像主要大部分出現在拍攝夜景,在圖像的黑暗的夜空中,出線了一些孤立的亮點。可以說其原因是由于CCD無法處理較慢的快門速度所帶來的巨大的工作量,致使一些特定的像素失去控制而造成的。為了防止產生這種圖像噪音,部分數碼相機中配備了被稱為"降噪"的功能。

    ????如果使用降噪功能,在記錄圖像之前就會利用數字處理方法來消除圖像噪音,因此在保存完畢以前就需要花費一點額外的時間。

    2、用JPEG格式對圖像壓縮而產生的圖像噪音

    ????由于JPEG格式的圖像在縮小圖像尺寸后圖像仍顯得很自然,因此就可以利用特殊的方法來減小圖像數據。此時,它就會以上下左右8×8個像素為一個單位進行處理。因此尤其是在8×8個像素邊緣的位置就會與下一個8×8個像素單位發生不自然的結合。

    ????由JPEG格式壓縮而產生的圖像噪音也被稱為馬賽克噪音(Block Noise),壓縮率越高,圖像噪音就越明顯。

    ????雖然把圖像縮小后這種噪音也會變得看不出來,但放大打印后,一進行色彩補償就表現得非常明顯。這種圖像噪音可以通過利用盡可能高的畫質或者利用JPEG格式以外的方法來記錄圖像而得以解決。

    3、模糊過濾造成的圖像噪音

    ????模糊過濾造成的圖像噪音和JPEG一樣,在對圖像進行處理時造成的圖像噪音。有時是在數碼相機內部處理過程中產生的,有時是利用圖像潤色軟件進行處理時產生的。對于尺寸較小的圖像,為了使圖像顯得更清晰而強調其色彩邊緣時就會產生圖像噪音。

    ????所謂的清晰處理就是指數碼相機具有的強調圖像色彩邊緣的功能和圖像編輯軟件的“模糊過濾(Unsharp Mask)”功能。在不同款式的數碼相機中也有一些相機會對整個圖像進行色彩邊緣的強調。而處理以后就會在原來的邊緣外側出現其他顏色的色線。

    ?? 如果將圖像尺寸縮小以后用于因特網的話,圖像不是總覺得會變得模糊不清嗎?此時如果利用“模糊過濾”功能對圖像進行清晰處理,圖像看起來效果就會好一些。不過由于產生了圖像噪音,在進行第二次或第三次處理時,這種圖像噪音就顯得很麻煩。切忌不要因為處理過度而使圖像顯得過于粗糙。?

    ????這里值得一題的是光圈F值愈小,在同一單位時間內的進光量便愈多,而且上一級的進光量剛是下一級的一倍,例如光圈從F8調整到F5.6,進光量便多一倍,我們也說光圈開大了一級。多數非專業數碼相機鏡頭的焦距短、物理口徑很小,F8時光圈的物理孔徑已經很小了,繼續縮小就會發生衍射之類的光學現象,影響成像。所以一般非專業數碼相機的最小光圈都在F8至F11,而專業型數碼相機感光器件面積大,鏡頭距感光器件距離遠,光圈值可以很小。對于消費型數碼相機而言,光圈F值常常介于F2.8 - F16。此外許多數碼相機在調整光圈時,可以做1/3級的調整。

    posted @ 2006-09-25 15:00 ericli 閱讀(266) | 評論 (0)編輯 收藏

    2006年9月13日 #

    SQL優化原則


    ?SQL優化原則
    ?
    1、使用索引來更快地遍歷表。
    缺省情況下建立的索引是非群集索引,但有時它并不是最佳的。在非群集索引下,數據在物理上隨機存放在數據頁上。合理的索引設計要建立在
    對各種查詢的分析和預測上。一般來說:
    a.有大量重復值、且經常有范圍查詢( > ,< ,> =,< =)和order by、group by發生的列,可考
    慮建立群集索引;
    b.經常同時存取多列,且每列都含有重復值可考慮建立組合索引;
    c.組合索引要盡量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。索引雖有助于提高性能但不是索引越多越好,恰好相反過多的索引會導致系統低效。用戶在表中每加進一個索引,維護索引集合就要做相應的更新工作。
    2、在海量查詢時盡量少用格式轉換。
    3、ORDER BY和GROPU BY使用ORDER BY和GROUP BY短語,任何一種索引都有助于SELECT的性能提高。
    7、任何對列的操作都將導致表掃描,它包括數據庫函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。
    4、IN、OR子句常會使用工作表,使索引失效。如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。

    Sql的優化原則2:
    1、只要能滿足你的需求,應盡可能使用更小的數據類型:例如使用MEDIUMINT代替INT
    2、盡量把所有的列設置為NOT NULL,如果你要保存NULL,手動去設置它,而不是把它設為默認值。
    3、盡量少用VARCHAR、TEXT、BLOB類型
    4、如果你的數據只有你所知的少量的幾個。最好使用ENUM類型
    5、正如graymice所講的那樣,建立索引。
    以下是我做的一個實驗,可以發現索引能極大地提高查詢的效率:

    我有一個會員信息表users,里邊有37365條用戶記錄:

    在不加索引的時候進行查詢:
    sql語句A:
    select * from users where username like ’%許%’;
    在Mysql-Front中的8次查詢時長為:1.40,0.54,0.54,0.54,0.53,0.55,0.54 共找到960條記錄

    sql語句B:
    select * from users where username like ’許%’;
    在Mysql-Front中的8次查詢時長為:0.53,0.53,0.53,0.54,0.53,0.53,0.54,0.54 共找到836條記錄

    sql語句C:
    select * from users where username like ’%許’;
    在Mysql-Front中的8次查詢時長為:0.51,0.51,0.52,0.52,0.51,0.51,0.52,0.51 共找到7條記錄

    為username列添加索引:
    create index usernameindex on users(username(6));

    再次查詢:
    sql語句A:
    select * from users where username like ’%許%’;
    在Mysql-Front中的8次查詢時長為:0.35,0.34,0.34,0.35,0.34,0.34,0.35,0.34 共找到960條記錄

    sql語句B:
    select * from users where username like ’許%’;
    在Mysql-Front中的8次查詢時長為:0.06,0.07,0.07,0.07,0.07,0.07,0.06,0.06 共找到836條記錄

    sql語句C:
    select * from users where username like ’%許’;
    在Mysql-Front中的8次查詢時長為:0.32,0.31,0.31,0.32,0.31,0.32,0.31,0.31 共找到7條記錄

    在實驗過程中,我沒有另開任何程序,以上的數據說明在單表查詢中,建立索引的可以極大地提高查詢速度。
    另外要說的是如果建立了索引,對于like ’許%’類型的查詢,速度提升是最明顯的。因此,我們在寫sql語句的時候也盡量采用這種方式查詢。

    對于多表查詢我們的優化原則是:

    盡量將索引建立在:left join on/right join on ... +條件,的條件語句中所涉及的字段上。

    多表查詢比單表查詢更能體現索引的優勢。

    6、索引的建立原則:
    如果一列的中數據的前綴重復值很少,我們最好就只索引這個前綴。Mysql支持這種索引。我在上面用到的索引方法就是對username最左邊的6個字符進行索引。索引越短,占用的

    磁盤空間越少,在檢索過程中花的時間也越少。這方法可以對最多左255個字符進行索引。

    在很多場合,我們可以給建立多列數據建立索引。

    索引應該建立在查詢條件中進行比較的字段上,而不是建立在我們要找出來并且顯示的字段上

    7、限制索引的使用的避歸。
    7.1? IN、OR子句常會使用工作表,使索引失效。
    如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。這句話怎么理解決,請舉個例子

    例子如下:
    如果在fields1和fields2上同時建立了索引,fields1為主索引
    以下sql會用到索引
    select * from tablename1 where fields1=’value1’ and fields2=’value2’
    以下sql不會用到索引
    select * from tablename1 where fields1=’value1’ or fields2=’value2’
    7.2 使用IS NULL 或IS NOT NULL
    ???????? 使用IS NULL 或IS NOT NULL同樣會限制索引的使用。因為NULL值并沒有被定義。在SQL語句中使用NULL會有很多的麻煩。因此建議開???? 發人員在建表時,把需要索引的列設成NOT NULL。如果被索引的列在某些行中存在NULL值,就不會使用這個索引(除非索引是一個位圖索引,關于位圖索引在稍后在詳細討論)。

    7.3 使用函數
    如果不使用基于函數的索引,那么在SQL語句的WHERE子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引。下面的查詢不會使用索引(只要它不是基于函數的索引)
    ?? select empno,ename,deptno
    ????????? from?? emp
    ????????? where? trunc(hiredate)='01-MAY-81';
    ????????? 把上面的語句改成下面的語句,這樣就可以通過索引進行查找。
    ????????? select empno,ename,deptno
    ????????? from?? emp
    ????????? where? hiredate<(to_date('01-MAY-81')+0.9999);

    7.4 比較不匹配的數據類型
    比較不匹配的數據類型也是比較難于發現的性能問題之一。注意下面查詢的例子,account_number是一個VARCHAR2類型,在account_number字段上有索引。下面的語句將執行全表掃描。
    ???????? select bank_name,address,city,state,zip
    ???????? from?? banks
    ???????? where? account_number = 990354;
    ???????? Oracle可以自動把where子句變成to_number(account_number)=990354,這樣就限制了索引的使用,改成下面的查詢就可以使用索引:
    ???????? select bank_name,address,city,state,zip
    ???????? from?? banks
    ???????? where? account_number ='990354';
    ???? 特別注意:不匹配的數據類型之間比較會讓Oracle自動限制索引的使用,即便對這個查詢執行Explain Plan也不能讓您明白為什么做了一?????????????? 次“全表掃描”。

    補充:
    1.索引帶來查詢上的速度的大大提升,但索引也占用了額外的硬盤空間(當然現在一般硬盤空間不成問題),而且往表中插入新記錄時索引也要隨著更新這也需要一定時間.
    有些表如果經常insert,而較少select,就不用加索引了.不然每次寫入數據都要重新改寫索引,花費時間;
    這個視實際情況而定,通常情況下索引是必需的.
    2.我在對查詢效率有懷疑的時候,一般是直接用Mysql的Explain來跟蹤查詢情況.
    你用Mysql-Front是通過時長來比較,我覺得如果從查詢時掃描字段的次數來比較更精確一些.

    ?

    ?

    posted @ 2006-09-13 20:25 ericli 閱讀(509) | 評論 (3)編輯 收藏

    取當前日期 到 前3個月的sql記錄 怎么寫

    select * from t where 日期字段名字>DATEADD ( mm, -3, getdate())

    //t 是你的表名

    ?

    ?


    現在程序里得到當前時間和3個月前的時間
    Date nowDate=new Date();
    Date oldDate=new Date();
    oldDate.setMonth(oldDate.getMonth()-3);

    select * from tab where 日期字段>oldDate and 日期字段<newDate

    posted @ 2006-09-13 20:24 ericli 閱讀(1940) | 評論 (0)編輯 收藏

    Struts初始化

    我在幾個月前曾經發表過一個帖子,就是和大家一起學習struts源代碼。成為一名合格的程序員,閱讀大量的優秀程序是必不可少的。只看書是不會讓你水平有很大提高的,要多看多寫。
    本來是打算等下面幾篇文章寫好后一起發布的,這樣大家可能才能看得明白些,但是根據我現在的狀況,估計還要一、兩個月。所以,為了防止在struts源代碼發生過大變化后我的文章就沒有太大價值了,所以就提前發表了,霍霍~~~
    我的email為:mariah_fan@hotmail.com,有什么不對的地方請大家指正:)
    struts作為J2EE的MVC框架已經取得了很大的成功,下面將分幾篇文章說明struts源程序的結構。
    第一篇? struts的初始化

    struts 的核心類是org.apache.struts.action.ActionServlet,這個類將會在struts第一次使用時,
    作為servlet初始化并存入tomcat容器。很顯然的,初始化將會調用init方法初始化相應的數據。

    一、initInternal()方法:
    ??? 通過調用MessageResources.getMessageResources(internalName)方法生成一個
    ??? MessageResources類,getMessageResources是通過調用MessageResourcesFactory.
    ??? createResources(config)來實現的。至于MessageResourcesFactory是一個abstract類,任何
    ??? 繼承自它的類都要實現createResources方法,生成MessageResources對象。整個程序生成
    ??? MessageResourcesFactory使用了如下技巧:
    ??? MessageResourcesFactory.factoryClass = factoryClass;
    ??? MessageResourcesFactory.clazz = null;
    ??? 首先會通過factoryClass來定義一個類全名,然后通過ClassLoader.loadClass
    ??? (factoryClass)方法來生成這個類,并賦給clazz,然后通過newInstance來生成一個對象。
    ??? 在本程序中,生成MessageResources對象實際就是對如下屬性進行了初始化:
    ??? this.factory = factory;("org.apache.struts.util.PropertyMessageResourcesFactory")
    ??? this.config = config;("org.apache.struts.action.ActionResources")
    ??? this.returnNull = returnNull;(true/false)

    ??? 對于MessageResources類的作用是根據不同的Locate來格式化相應的string。或者把你需要改變
    ??? 的string存放到數組中,然后通過getMessage(Locale locale, String key, Object args[])
    ??? 方法來格式化。然后把格式好的string存放到HashMap里,這樣就可以為以后重用。這里的key是
    ??? 使用的locale.toString() + "." + key

    ??? 在PropertyMessageResources中的loadLocale方法用來讀取resource的初始化信息。首先它會
    ??? 通過一個HashMap檢測這個localKey相關的message是否已經被初始化了,如果被初始化過就跳
    ??? 出,檢測的方法是locales.get(localeKey) != null。
    ??? 然后會讀取如下一個文件:
    ??? org/apache/struts/action/ActionResources_(localKey).properties,然后進行如下操作:
    ??? Properties props = new Properties();
    ??? ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    ??? is = classLoader.getResourceAsStream(name);
    ??? props.load(is);
    ??? Iterator names = props.keySet().iterator();
    ??????? while (names.hasNext()) {
    ??????????? String key = (String) names.next();
    ??????????? if (log.isTraceEnabled()) {
    ??????????????? log.trace("? Saving message key '" + messageKey(localeKey, key));
    ??????????? }
    ??????????? messages.put(messageKey(localeKey, key), props.getProperty(key));
    ??? }

    ??? PropertyMessageResources 就是通過上面的loadLocale方法查找與Locale locale, String key
    ??? 相對對應的Message.查找的次序如下locale.toString(),然后是
    ??? localeKey = localeKey.substring(0, underscore),然后是defaultLocale,然后是key。

    ??? 最后,resource類的結構如下:
    ??? PropertyMessageResources extends MessageResources
    ??? PropertyMessageResourcesFactory extends MessageResourcesFactory

    二、initOther()方法:
    ??? 從servlet中獲取config和debug兩個參數,然后初始化ConvertUtils對象。由于
    ??? ConvertUtils.deregister()的初始化,所有的Converter都是有初始值的,所以這里Struts自己
    ??? 把這些初始值設置為null,即轉換出錯的時候返回null,而不是初始值。使用ConvertUtils類的
    ??? 原因是由于從form傳輸過來的都是String類型的值,所以我們要把它們轉換成相應的類型。

    ??? 提到幾個技巧:
    ??? *public boolean isIndexed() {
    ???????? if (type == null) {
    ???????????? return (false);
    ???????? //技巧一:判斷是否是一個Array類的方法
    ???????? } else if (type.isArray()) {
    ???????????? return (true);
    ???????? //技巧二:判斷type是否是List的一個父類或者父接口,或者與List為同一個類
    ???????? //要注意如果List是另一個primitive的TYPE類,那么type必須也是這個類才會
    ???????? //返回true,否則都是false。注意long.TYPE與Long.class是不同的
    ???????? } else if (List.class.isAssignableFrom(type)) {
    ???????????? return (true);
    ???????? } else {
    ??????????? return (false);
    ???????? }
    ???? }

    ??? *//componentType為Array類所存儲的元素的類別
    ???? Class componentType = indexedProperty.getClass().getComponentType();
    ???? //生成一個新的Array
    ???? Object newArray = Array.newInstance(componentType, (index + 1));
    ???? System.arraycopy(indexedProperty, 0, newArray, 0, length);
    ???? indexedProperty = newArray;
    ???? set(name, indexedProperty);
    ???? int newLength = Array.getLength(indexedProperty);
    ???? for (int i = length; i < newLength; i++) {
    ??????? Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType));
    ???? }

    三、initServlet()方法:
    ??? 這個方法主要是通過digester類解析web.xml,對String servletMapping屬性進行初始化。對于
    ??? digester說明如下:這是一個基于DOM的SAX實現的類,它是事件觸發的,根據xml文件的結構,
    ??? 每次讀到一個節點元素就會觸發一個事件。

    ??? InputStream input = getServletContext().getResourceAsStream("/WEB-INF/web.xml");
    ??? 這是一個比較少見的方法。首先通過this.servletName = getServletConfig().
    ??? getServletName()獲取servlet的名稱,然后根據
    ??? if (servletName.equals(this.servletName)) {
    ??????? this.servletMapping = urlPattern;
    ??? }
    ??? 來判斷當前讀到的servlet名稱是否是我們運行的servlet的名稱,如果是,就把url-pattern作為
    ??? 我們的servletMapping。

    四、getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this)
    ??? 把自己存儲到servletContext中,屬性名為Globals.ACTION_SERVLET_KEY。

    五、ModuleConfig moduleConfig = initModuleConfig("", config)
    ??? 這個方法使用由initOther()方法獲取的config值為要解析的xml路徑,用來初始化ModuleConfig。
    ??? 它首先采用與生成MessageResourcesFactory同樣的方法產生一個MessageResourcesFactory對象:
    ??? MessageResourcesFactory為一個抽象類,每一個繼承它的類都要實現
    ??? createModuleConfig(String prefix)方法。本程序使用的缺省的MessageResourcesFactory類為
    ??? org.apache.struts.config.impl.DefaultModuleConfigFactory,它
    ??? 的createModuleConfig(String prefix)方法會生成一個ModuleConfigImpl類。

    ??? ModuleConfigImpl類相當于一個JavaBean,用來存放一個web模塊運行時所需要的配置信息。當
    ??? 然,一個web模塊可以擁有多個ModuleConfig,但是缺省的是prefix長度為0的ModuleConifg。它
    ??? 的每個屬性幾乎都是由HashMap組成的,它通過一個configured布爾值來描述當前的ModuleConfig
    ??? 是否已經被初始化完畢,在每存放一個屬性的時候都會監測這個值。如果初始化完畢而還要改變
    ??? 里面的屬性值,則會報出IllegalStateException("Configuration is frozen")異常,現在對它
    ??? 的屬性簡單說明如下:
    ??? * protected HashMap actionConfigs:
    ????? 這個HashMap用來存儲ActionConfig對象。
    ??? * protected HashMap dataSources
    ????? 這個HashMap用來存儲DataSourceConfig對象。
    ??? * protected HashMap exceptions
    ????? 這個HashMap用來存儲ExceptionConfig對象。
    ??? * protected HashMap formBeans
    ????? 這個HashMap用來存儲FormBeanConfig對象。
    ??? * protected HashMap forwards
    ????? 這個HashMap用來存儲ForwardConfig對象。
    ??? * protected HashMap messageResources
    ????? 這個HashMap用來存儲MessageResourcesConfig對象。
    ??? * protected ArrayList plugIns
    ????? 這個HashMap用來存儲PlugInConfig對象。
    ??? * protected ControllerConfig controllerConfig
    ????? ControllerConfig類
    ??? * protected boolean configured
    ????? 標志這個ModuleConfig是(true)否(false)配置完成。
    ??? * protected String prefix
    ????? 用來標志和區分ModuleConfig類,同時在使用上面的config類初始化相應的資源以后,也是通
    ????? 過這個prefix來區分所屬的不同的web模塊。
    ??? * protected String actionMappingClass = "org.apache.struts.action.ActionMapping"
    ????? ActionMapping類名,缺省為org.apache.struts.action.ActionMapping。

    ??? 初始化ModuleConfig的方法如下:
    ??? 首先是使用getServletConfig().getInitParameter("mapping")來獲取設定的ActionMapping類
    ??? 名,然后通過initConfigDigester()方法來生成一個digester。最后用","分隔config,對每一
    ??? 塊調用parseModuleConfigFile(prefix, paths, config, digester, path)方法解析。注意,這
    ??? 個方法實際上只有兩個參數是有意義的:path為我們要解析的xml文件,config用來初始化完成
    ??? 后保存到servletContext中。

    ??? 如果ModuleConfig中存放的FormBeanConfig為Dydamic類型,那么就調用
    ??? DynaActionFormClass.createDynaActionFormClass(FormBeanConfig)初始化
    ??? DynaActionFormClass,并存放到DynaActionFormClass.dynaClasses 的 static HashMap中。這
    ??? 里的key為FormBeanConfig.getName() + moduleConfig.getPrefix()。
    ???
    ??? 如果當前的ModuleConfig為缺省的ModuleConfig,那么將會調用如下幾個方法:
    ??? defaultControllerConfig(config)
    ??? defaultMessageResourcesConfig(config)
    ??? defaultFormBeansConfig(config)
    ??? defaultForwardsConfig(config)
    ??? defaultMappingsConfig(config)
    ??? 在struts1.1以后,這個特例將會被廢棄:

    ??? defaultControllerConfig(config)為ControllerConfig通過getInitParameter(s)方法初始化如
    ??? 下幾個屬性:bufferSize,content,locale(true/false),maxFileSize,nocache(true/false)
    ??? ,multipartClass,tempDir。

    ??? defaultMessageResourcesConfig(config)為MessageResourcesConfig通過getInitParameter(s)
    ??? 方法初始化如下幾個屬性:application,factory,null(true/false)。

    ??? 其它的幾個方法就是獲取不同的對象,然后把它們相應的存儲到servlet中。關心如下:
    ??? ActionFormBeans=>FormBeanConfig,ActionForwards=>ForwardConfig,
    ??? ActionMappings=>ActionConfig。

    六、initModuleMessageResources(ModuleConfig config)
    ??? 通過存儲在ModuleConfig中的MessageResourcesConfig對象,逐個初始化MessageResource,
    ??? 然后再把初始化好的MessageResources存放到ServletContext中,attributeName為
    ??? MessageResourcesConfig.getKey() + ModuleConfig.getPrefix()。

    七、initModuleDataSources(ModuleConfig config)
    ??? 通過存儲在ModuleConfig中的DataSourceConfig對象,逐個初始化DataSource。然后對于每一個
    ??? DateSource通過BeanUtils.populate(ds, dscs[i].getProperties())方法初始化其屬性。再把初
    ??? 始化好的DateSource存放到ServletContext中,attributeName為
    ??? DataSourceConfig.getKey() + ModuleConfig.getPrefix()。同時也存放到名位dataSources的
    ??? FastHashMap中,key為DataSourceConfig.getKey()。

    ??? 這里還會根據生成的DateSource對象是否是GenericDataSource類型,如果是則調用
    ??? GenericDataSource.open()方法。GenericDataSource是一個非常簡單的數據庫連接池,它的
    ??? open()方法用來初始化連接池,生成最小數目的GenericConnection,這里的open()方法根據
    ??? String driver變量是否為null來判斷是否已經被初始化過。需要仔細說明的是getConnection()
    ??? 方法,它首先從連接池中取出GenericConnection對象,然后檢查其是否是可鏈接的,如果是就
    ??? 返回,否則繼續取出,同時activeCount-1。如果沒有取到,則會檢查當前可使用的
    ??? GenericConnection是否達到最大值(activeCount < maxCount),如果沒有,調用
    ??? createConnection()方法聲成一個新的GenericConnection,然后檢查其是否是可鏈接,如果可以
    ??? 則返回。returnConnection(GenericConnection conn)方法則是通過把GenericConnection放回到
    ??? 連接池,然后activeCount-1。

    ??? 這個方法中使用到了ServletContextWriter類,DateSource的log信息就通過這個類寫入。對這個
    ??? 類說明如下:
    ??? 它繼承自PrintWriter,而PrintWriter又繼承自Writer。Writer類所作的事情就是在同步的情況下
    ??? 調用abstract方法:abstract public void write(char cbuf[], int off, int len),這個方法
    ??? 將會根據調用者的需要由調用者實現。
    ??? PrintWriter則首先通過ensureOpen()方法檢驗這個類中是否有寫入的對象(Writer類或其子類),
    ??? 如果有則根據不同的情況調用這個寫入對象的write方法(out.write(....))。這個類的print(...)
    ??? 方法就是據不同的情況調用相應的write(...)方法。而println(...)與之的區別就是每次多寫入一
    ??? 個換行字符串。還有一個區別是println(...)會根據是否需要autoflush進行flush,而write(...)
    ??? 方法不會。
    ??? ServletContextWriter類的作用是把字符寫入ServletContext中。ServletContextWriter類方法中
    ??? 真正實現了write方法:
    ??? public void write(char c) {
    ??????? if (c == '\n')
    ??????????? flush();
    ??????? else if (c != '\r')
    ??????????? buffer.append(c);
    ??? }
    ??? public void flush() {
    ??????? if (buffer.length() > 0) {
    ??????????? context.log(buffer.toString());
    ??????????? buffer.setLength(0);
    ??????? }
    ??? }

    八、initModulePlugIns(moduleConfig)
    ??? 通過存儲在ModuleConfig中的PlugInConfig對象,逐個初始化PlugIn對象,存放到一個數組中,
    ??? 然后再把這個數組存放到ServletContext中,attributeName為
    ??? Globals.PLUG_INS_KEY + ModuleConfig.getPrefix()。

    ??? 對每一個生成的PlugIn對象通過
    ??? BeanUtils.populate(plugIns[i], plugInConfigs[i].getProperties())方法初始化其屬性。然后
    ??? 再把PlugInConfig對象存放到由其生成的PlugIn對象中。

    ??? 最后,通過plugIns[i].init(this, (ModuleConfig) config)初始化這個plugIn對象。

    九、初始化結束
    ??? 完成了這個初始化以后,會調用ModuleConfig.freeze()令這個ModuleConfig變得不可改變。然后
    ??? 會遍歷ServletConfig中的initParameterNames,如果有以"config/"開頭的,則通過這個parameter
    ??? 的值繼續初始化其它的ModuleConfig,且這個ModuleConfig的prefix為"config/"后的字符串。
    ???
    ??? 同樣調用如下方法:
    ??? initModuleMessageResources(moduleConfig);
    ??? initModuleDataSources(moduleConfig);
    ??? initModulePlugIns(moduleConfig);
    ??? moduleConfig.freeze();

    ??? 最后調用destroyConfigDigester()釋放內存。

    posted @ 2006-09-13 20:24 ericli 閱讀(367) | 評論 (0)編輯 收藏

    Struts1.1源碼解析

    Struts1.1b3部分源代碼分析.
    作者:???? 文章來源:
    訪問次數: 次??? 加入時間:2006-05-12
    ?
    Struts1.1部分源代碼分析
    一:說明
    本文針對Struts1.1b3做分析,主要希望通過對源代碼的分析闡述Struts1.1的工作方式。
    本文不適合初學者參考,適合具有一定基于Struts開發的程序員參考。
    下面的描述;里面將會對ActionServlet,RequestProcessor,ModuleConfig等幾個類做一些
    說明。以注釋源代碼的方式,說明取工作流程。
    特別申明:Struts1.1代碼版權屬于Apache遵循The Apache Software License, Version 1.1.
    本文版權屬于孤魂一笑個人所有,任何個人或組織希望轉載,請與我聯系。并獲得我的授權
    方可轉載。

    二:ActionServlet分析
    我們先來看一下使用Struts的配置文件。


    action
    org.apache.struts.action.ActionServlet


    definitions-config
    /WEB-INF/tiles-defs.xml,/WEB-INF/tiles-tests-defs.xml,/WEB-INF/tiles-tutorial-defs.xml,
    /WEB-INF/tiles-examples-defs.xml


    definitions-debug
    0


    definitions-parser-details
    0


    definitions-parser-validate
    true

    ?

    config
    /WEB-INF/struts-config.xml

    ?

    config/examples
    /WEB-INF/struts-examples-config.xml

    ?

    config/test
    /WEB-INF/struts-tests-config.xml

    ?

    config/tutorial
    /WEB-INF/struts-tutorial-config.xml


    validate
    true


    debug
    2


    detail
    2

    ?

    application
    org.apache.struts.webapp.tiles.dev1-1.ApplicationResources


    2

    ?


    action
    *.do

    ?

    接下來我們來看一下ActionServlet的具體使用
    javax.servlet.http.HttpServlet
    |
    |-->org.apache.struts.action.ActionServlet
    所以本質上ActionServlet是一個普通的servlet,負責處理.do為后綴的Http請求.
    servlet在執行doGet(),doPost(),之前先調用init(),
    以下我們先分析一下init()方法
    /**
    * Initialize this servlet. Most of the processing has been factored into
    * support methods so that you can override particular functionality at a
    * fairly granular level.

    * servlet初始化操作,注意初始化順序
    * @exception ServletException if we cannot configure ourselves correctly
    */
    public void init() throws ServletException {
    //注意初始化的順序
    //Initialize our internal MessageResources bundle
    initInternal();
    //Initialize other global characteristics of the controller servlet
    //處理一些全局變量的設置如:debug,detail等
    initOther();
    //Initialize the servlet mapping under which our controller servlet
    //is being accessed. This will be used in the &html:form>
    //tag to generate correct destination URLs for form submissions
    //主要是注冊DTD文件以及解析web.xml關于ActionServlet的配置。如后綴名等.
    // Configure the processing rules that we need
    // digester.addCallMethod("web-app/servlet-mapping",
    // "addServletMapping", 2);
    // digester.addCallParam("web-app/servlet-mapping/servlet-name", 0);
    // digester.addCallParam("web-app/servlet-mapping/url-pattern", 1);
    //initServlet()的上面一段將把Struts默認的后綴名從web.xml中解析得到
    //也就是web.xml中的如下配置:
    //
    //action
    //*.do
    //默認以.do結尾的請求都將由Struts來處理,你可以自己修改
    //
    initServlet();

    // Initialize modules as needed
    //在Attribute中保存類實例
    getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
    //根據配置文件生成ModuleConfig,這是很重要的一步.下面會專門分析
    //在tiles的配置中先解析注釋為"Mark 0"的一個配置文件:/WEB-INF/struts-config.xml
    //使用initModuleConfig方法解析XML文件.
    //參數為prefix:"",paths:"/WEB-INF/struts-config.xml"
    ModuleConfig moduleConfig = initModuleConfig("", config);
    //初始化Message
    initModuleMessageResources(moduleConfig);
    //初始化JDBC DataSource
    initModuleDataSources(moduleConfig);
    //初始化PlunIn
    initModulePlugIns(moduleConfig);

    moduleConfig.freeze();
    //在Struts1.1以后可以使用多個配置文件,在解析完默認的配置文件也就是上面提到的
    //注釋為"Mark 0"的一個配置文件:/WEB-INF/struts-config.xml后解析其他的配置文件
    Enumeration names = getServletConfig().getInitParameterNames();
    //依次解析注釋為"Mark 1"、"Mark 2"、"Mark 3"對應配置文件
    while (names.hasMoreElements()) {
    //每一個配置文件的文件名
    String name = (String) names.nextElement();
    if (!name.startsWith("config/")) {
    continue;
    }
    //
    String prefix = name.substring(6);
    moduleConfig = initModuleConfig
    (prefix, getServletConfig().getInitParameter(name));

    initModuleMessageResources(moduleConfig);
    initModuleDataSources(moduleConfig);
    initModulePlugIns(moduleConfig);
    moduleConfig.freeze();
    }
    destroyConfigDigester();

    }
    /**
    * 此方法使用Digester解析XML,關于使用Digester的介紹參看我的另外一篇文章
    *
    Initialize the application configuration information for the
    * specified module.


    *
    * @param prefix Module prefix for this module
    * @param paths Comma-separated list of context-relative resource path(s)
    * for this modules's configuration resource(s)
    *
    * @exception ServletException if initialization cannot be performed
    * @since Struts 1.1
    */
    protected ModuleConfig initModuleConfig
    (String prefix, String paths) throws ServletException {

    if (log.isDebugEnabled()) {
    log.debug("Initializing module path '" + prefix +
    "' configuration from '" + paths + "'");
    }

    // Parse the configuration for this module
    ModuleConfig config = null;
    InputStream input = null;
    String mapping = null;
    try {
    //工廠方法創建ModuleConfig標記為:prefix
    ModuleConfigFactory factoryObject =
    ModuleConfigFactory.createFactory();
    config = factoryObject.createModuleConfig(prefix);

    // Support for module-wide ActionMapping type override
    mapping = getServletConfig().getInitParameter("mapping");
    if (mapping != null) {
    config.setActionMappingClass(mapping);
    }

    // Configure the Digester instance we will use
    //得到解析XML的digester
    Digester digester = initConfigDigester();

    // Process each specified resource path
    while (paths.length() > 0) {
    //開始解析指定路徑文件名的文件
    digester.push(config);
    String path = null;
    //文件是否為多個并且使用","分割
    int comma = paths.indexOf(',');
    //存在多個配置文件
    if (comma >= 0) {
    //先解析第一個
    path = paths.substring(0, comma).trim();
    //paths存放剩余的文件名下次再處理
    paths = paths.substring(comma + 1);
    } else {
    //當前只存在一個
    path = paths.trim();
    //沒有剩余,下次循環根據上面一句將會在唯一的循環退出點"point break"
    //退出循環
    paths = "";
    }
    //全部解析完成跳出循環
    //point break
    if (path.length() < 1) {
    break;
    }
    //根據文件名取文件
    URL url = getServletContext().getResource(path);
    InputSource is = new InputSource(url.toExternalForm());
    input = getServletContext().getResourceAsStream(path);
    is.setByteStream(input);
    digester.parse(is);
    //全局變量的形式把解析生成的ModuleConfig實例保存起來
    //如"Mark 1"處標記的"config/examples",
    //key為:"org.apache.struts.action.MODULEexamples"
    //Globals.MODULE_KEY值為:org.apache.struts.action.MODULE
    getServletContext().setAttribute
    (Globals.MODULE_KEY + prefix, config);
    input.close();
    }

    } catch (Throwable t) {
    log.error(internal.getMessage("configParse", paths), t);
    throw new UnavailableException
    (internal.getMessage("configParse", paths));
    } finally {
    if (input != null) {
    try {
    input.close();
    } catch (IOException e) {
    ;
    }
    }
    }

    // Force creation and registration of DynaActionFormClass instances
    // for all dynamic form beans we wil be using
    //根據ModuleConfig實例得到配置的FormBean的配置
    //注意:因為在Struts整個運行當中FormBean的實例要在Action的實例創建之前先創建
    //因為Action執行perform(1.1以前),execute(1.1)需要使用到FormBean
    FormBeanConfig fbs[] = config.findFormBeanConfigs();
    for (int i = 0; i < fbs.length; i++) {
    if (fbs[i].getDynamic()) {
    DynaActionFormClass.createDynaActionFormClass(fbs[i]);
    }
    }

    // Special handling for the default module (for
    // backwards compatibility only, will be removed later)
    //下面是生成一些實例
    if (prefix.length() < 1) {
    defaultControllerConfig(config);
    defaultMessageResourcesConfig(config);
    defaultFormBeansConfig(config);
    defaultForwardsConfig(config);
    defaultMappingsConfig(config);
    }

    // Return the completed configuration object
    //config.freeze(); // Now done after plugins init
    return (config);

    }

    到此初始化工作基本結束,下面將處理具體的Http請求。在Servlet協議中所有的post方法將調用
    以下方法來處理
    public void doPost(HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {}
    get方法也調用類似的方法來處理

    在Struts中post,get方法都調用同一個方法
    process(request, response);來處理具體的請求
    如下:
    /**
    * 對每一個提交過來的Action進行處理
    * Perform the standard request processing for this request, and create
    * the corresponding response.
    *
    * @param request The servlet request we are processing
    * @param response The servlet response we are creating
    *
    * @exception IOException if an input/output error occurs
    * @exception ServletException if a servlet exception is thrown
    */
    protected void process(HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {
    //設置或刪除Attribute
    RequestUtils.selectModule(request, getServletContext());
    //具體的處理交給RequestProcessor去處理HttpRequest,HttpResponse
    //這是一個很典型的設計模式
    //下面我們將詳細來分析RequestProcessor,很容易理解Struts的運行方式
    getRequestProcessor(getModuleConfig(request)).process(request, response);
    }

    三:RequestProcessor分析
    通過前面的分析我們知道Struts中對HttpRequest,HttpResponse的處理都交給RequestProcessor
    的process()方法來處理。下面我們來看看process方法
    /**
    *
    Process an HttpServletRequest and create the
    * corresponding HttpServletResponse.


    *
    * @param request The servlet request we are processing
    * @param response The servlet response we are creating
    *
    * @exception IOException if an input/output error occurs
    * @exception ServletException if a processing exception occurs
    */
    public void process(HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    // Wrap multipart requests with a special wrapper
    //如果是upload,返回一個MultipartRequestWrapper()
    request = processMultipart(request);

    // Identify the path component we will use to select a mapping
    //對request進行分析得到提交過來的Form Action
    String path = processPath(request, response);
    if (path == null) {
    return;
    }
    if (log.isInfoEnabled()) {
    log.info("Processing a '" + request.getMethod() +
    "' for path '" + path + "'");
    }

    // Select a Locale for the current user if requested
    //本地化處理
    processLocale(request, response);

    // Set the content type and no-caching headers if requested
    processContent(request, response);
    //設置Cache不保存
    processNoCache(request, response);

    // General purpose preprocessing hook
    if (!processPreprocess(request, response)) {
    return;
    }

    // Identify the mapping for this request
    //得到path以后,根據配置文件(struts-config.xml)的相關配置來得到一個
    //ActionMapping的實例
    //ActionMapping繼承ActionConfig
    //仔細看一下ActionMapping的代碼就能發現:
    //下面的一段將解析影射一個ActionMapping的實例
    //在ActionServlet在初始化的時候實際上已經把所有的ActionMapping的實例
    //都已經創建好了。processMapping方法實際上是從Attribute中去得到已經
    //保存好的ActionMapping的實例,可以理解為在Tomcat啟動的時候已經
    //把所有的ActionMapping保存在Attribute里面。所以在Tomcat啟動的時候
    //比較慢,如果Struts-config.xml有問題啟動就會出錯。
    /***

    type="org.apache.struts.webapp.tiles.test.TestActionTileAction">

    ?

    **/
    //****注意得到創建實例的順序
    //ActionMapping實例已經創建好了,現在從Atribute中取到
    ActionMapping mapping = processMapping(request, response, path);
    if (mapping == null) {
    return;
    }

    // Check for any role required to perform this action
    if (!processRoles(request, response, mapping)) {
    return;
    }

    // Process any ActionForm bean related to this request
    //根據mapping得到ActionForm的實例。
    //同名ActionForm在系統中只會創建一次。
    ActionForm form = processActionForm(request, response, mapping);
    //壓棧
    processPopulate(request, response, form, mapping);
    //處理校驗,調用ActionForm的validate方法
    //假如出錯將會返回到前一頁面
    //也就是說在Action還沒有創建之前就將做校驗
    if (!processValidate(request, response, form, mapping)) {
    return;
    }

    // Process a forward or include specified by this mapping
    if (!processForward(request, response, mapping)) {
    return;
    }
    if (!processInclude(request, response, mapping)) {
    return;
    }

    // Create or acquire the Action instance to process this request
    //在得到ActionMapping、ActionForm的實例后接下來得到Action實例
    //實例如果已經創建從Map里面去取如果沒有創建一個并保存在Map里面
    //對保存Action實例的Map 實現線程同步
    Action action = processActionCreate(request, response, mapping);
    if (action == null) {
    return;
    }

    // Call the Action instance itself
    //在ActionMapping、ActionForm、Action實例創建好以后
    //調用Action的execute()方法得到一個ActionForward
    //因為所有的可執行Action都必須有override Action的execute()/perform()方法
    ActionForward forward =
    processActionPerform(request, response,
    action, form, mapping);

    // Process the returned ActionForward instance
    //Action已經正常執行,執行結束后將返回到另外一個頁面
    processActionForward(request, response, forward);

    }

    仔細閱讀上面的代碼,要特別注意ActionMapping、ActionForm、Action的實例是依次創建的。
    創建完以后才去執行Action的execute()方法。為什么要依次創建ActionMapping、ActionForm
    、Action??????


    四:ModuleConfig分析
    現在我們很有必要了解一下ModuleConfig這個類,因為太多地方用到了。
    實際上ModuleConfig是一個接口有一個實現。org.apache.struts.config.impl.ModuleConfigImpl
    具體實現我就沒有不要去分析了。我們來看看這個接口。

    package org.apache.struts.config;

    /**
    *
    The collection of static configuration information that describes a
    * Struts-based module. Multiple modules are identified by
    * a prefix at the beginning of the context
    * relative portion of the request URI. If no module prefix can be
    * matched, the default configuration (with a prefix equal to a zero-length
    * string) is selected, which is elegantly backwards compatible with the
    * previous Struts behavior that only supported one module.


    *
    * @author Rob Leland
    * @version $Revision: 1.2 $ $Date: 2002/12/22 05:31:14 $
    * @since Struts 1.1
    */
    public interface ModuleConfig {
    /**
    * Has this module been completely configured yet. Once this flag
    * has been set, any attempt to modify the configuration will return an
    * IllegalStateException.
    */
    boolean getConfigured();

    /**
    * The controller configuration object for this module.
    */
    ControllerConfig getControllerConfig();
    /**
    * The controller configuration object for this module.
    * @param cc The controller configuration object for this module.
    */

    void setControllerConfig(ControllerConfig cc);

    /**
    * The prefix of the context-relative portion of the request URI, used to
    * select this configuration versus others supported by the controller
    * servlet. A configuration with a prefix of a zero-length String is the
    * default configuration for this web module.
    */
    String getPrefix();

    /**
    * The prefix of the context-relative portion of the request URI, used to
    * select this configuration versus others supported by the controller
    * servlet. A configuration with a prefix of a zero-length String is the
    * default configuration for this web module.
    */
    public void setPrefix(String prefix);
    /**
    * The default class name to be used when creating action mapping
    * instances.
    */
    String getActionMappingClass();
    /**
    * The default class name to be used when creating action mapping
    * instances.
    * @param actionMappingClass default class name to be used when creating action mapping
    * instances.
    */

    void setActionMappingClass(String actionMappingClass);

    /**
    * Add a new ActionConfig instance to the set associated
    * with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void addActionConfig(ActionConfig config);

    /**
    * Add a new DataSourceConfig instance to the set associated
    * with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void addDataSourceConfig(DataSourceConfig config);

    /**
    * Add a new ExceptionConfig instance to the set associated
    * with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void addExceptionConfig(ExceptionConfig config);

    /**
    * Add a new FormBeanConfig instance to the set associated
    * with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void addFormBeanConfig(FormBeanConfig config);

    /**
    * Add a new ForwardConfig instance to the set of global
    * forwards associated with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void addForwardConfig(ForwardConfig config);

    /**
    * Add a new MessageResourcesConfig instance to the set
    * associated with this module.
    *
    * @param config The new configuration instance to be added
    *
    * @exception IllegalStateException if this module configuration
    * has been frozen
    */
    void addMessageResourcesConfig(MessageResourcesConfig config);

    /**
    * Add a newly configured {@link org.apache.struts.config.PlugInConfig} instance to the set of
    * plug-in Actions for this module.
    *
    * @param plugInConfig The new configuration instance to be added
    */
    void addPlugInConfig(PlugInConfig plugInConfig);

    /**
    * Return the action configuration for the specified path, if any;
    * otherwise return null.
    *
    * @param path Path of the action configuration to return
    */
    ActionConfig findActionConfig(String path);

    /**
    * Return the action configurations for this module. If there are
    * none, a zero-length array is returned.
    */
    ActionConfig[] findActionConfigs();

    /**
    * Return the data source configuration for the specified key, if any;
    * otherwise return null.
    *
    * @param key Key of the data source configuration to return
    */
    DataSourceConfig findDataSourceConfig(String key);

    /**
    * Return the data source configurations for this module. If there
    * are none, a zero-length array is returned.
    */
    DataSourceConfig[] findDataSourceConfigs();

    /**
    * Return the exception configuration for the specified type, if any;
    * otherwise return null.
    *
    * @param type Exception class name to find a configuration for
    */
    ExceptionConfig findExceptionConfig(String type);

    /**
    * Return the exception configurations for this module. If there
    * are none, a zero-length array is returned.
    */
    ExceptionConfig[] findExceptionConfigs();

    /**
    * Return the form bean configuration for the specified key, if any;
    * otherwise return null.
    *
    * @param name Name of the form bean configuration to return
    */
    FormBeanConfig findFormBeanConfig(String name);

    /**
    * Return the form bean configurations for this module. If there
    * are none, a zero-length array is returned.
    */
    FormBeanConfig[] findFormBeanConfigs();

    /**
    * Return the forward configuration for the specified key, if any;
    * otherwise return null.
    *
    * @param name Name of the forward configuration to return
    */
    ForwardConfig findForwardConfig(String name);

    /**
    * Return the form bean configurations for this module. If there
    * are none, a zero-length array is returned.
    */
    ForwardConfig[] findForwardConfigs();

    /**
    * Return the message resources configuration for the specified key,
    * if any; otherwise return null.
    *
    * @param key Key of the data source configuration to return
    */
    MessageResourcesConfig findMessageResourcesConfig(String key);

    /**
    * Return the message resources configurations for this module.
    * If there are none, a zero-length array is returned.
    */
    MessageResourcesConfig[] findMessageResourcesConfigs();

    /**
    * Return the configured plug-in actions for this module. If there
    * are none, a zero-length array is returned.
    */
    PlugInConfig[] findPlugInConfigs();

    /**
    * Freeze the configuration of this module. After this method
    * returns, any attempt to modify the configuration will return
    * an IllegalStateException.
    */
    void freeze();

    /**
    * Remove the specified action configuration instance.
    *
    * @param config ActionConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeActionConfig(ActionConfig config);

    /**
    * Remove the specified exception configuration instance.
    *
    * @param config ActionConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeExceptionConfig(ExceptionConfig config);

    /**
    * Remove the specified data source configuration instance.
    *
    * @param config DataSourceConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeDataSourceConfig(DataSourceConfig config);

    /**
    * Remove the specified form bean configuration instance.
    *
    * @param config FormBeanConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeFormBeanConfig(FormBeanConfig config);

    /**
    * Remove the specified forward configuration instance.
    *
    * @param config ForwardConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeForwardConfig(ForwardConfig config);

    /**
    * Remove the specified message resources configuration instance.
    *
    * @param config MessageResourcesConfig instance to be removed
    *
    * @exception java.lang.IllegalStateException if this module configuration
    * has been frozen
    */
    void removeMessageResourcesConfig(MessageResourcesConfig config);
    }


    上面的注釋已經非常清晰了。我就不去浪費大家的時間了,再想仔細看就去看他的實現。
    其實主要是對HashMap()的處理。

    五:ActionMapping分析
    最后我們實現很有必要看一下ActionMapping,因為你如果想清楚的了解Struts-config.xml
    這個配置文件的作用,你應該要知道ActionMapping
    前面已經說過ActionMapping繼承ActionConfig
    以下就是ActionMapping加的四個方法。
    /**
    *
    Find and return the ExceptionConfig instance defining
    * how exceptions of the specified type should be handled. This is
    * performed by checking local and then global configurations for the
    * specified exception's class, and then looking up the superclass chain
    * (again checking local and then global configurations). If no handler
    * configuration can be found, return null.


    *
    * @param type Exception class for which to find a handler
    * @since Struts 1.1
    */
    public ExceptionConfig findException(Class type) {

    }


    /**
    *
    Find and return the ForwardConfig instance defining
    * how forwarding to the specified logical name should be handled. This is
    * performed by checking local and then global configurations for the
    * specified forwarding configuration. If no forwarding configuration
    * can be found, return null.


    *
    * @param name Logical name of the forwarding instance to be returned
    */
    public ActionForward findForward(String name) {

    }


    /**
    *
    Return the logical names of all locally defined forwards for this
    * mapping. If there are no such forwards, a zero-length array
    * is returned.
    */
    public String[] findForwards() {
    }


    /**
    *

    Create (if necessary) and return an {@link ActionForward} that
    * corresponds to the input property of this Action.
    *
    * @since Struts 1.1b2
    */
    public ActionForward getInputForward() {

    }

    還是看以下他的基類ActionConfig吧
    public class ActionConfig implements Serializable {

    /**
    * Has configuration of this component been completed?
    */
    protected boolean configured = false;

    /**
    * The set of exception handling configurations for this
    * action, if any, keyed by the type property.
    */
    protected HashMap exceptions = new HashMap();

    /**
    * The set of local forward configurations for this action, if any,
    * keyed by the name property.
    */
    protected HashMap forwards = new HashMap();

    /**
    * The module configuration with which we are associated.
    */
    protected ModuleConfig moduleConfig = null;

    /**
    * The request-scope or session-scope attribute name under which our
    * form bean is accessed, if it is different from the form bean's
    * specified name.
    */
    protected String attribute = null;

    /**
    * Context-relative path of the web application resource that will process
    * this request via RequestDispatcher.forward(), instead of instantiating
    * and calling the Action class specified by "type".
    * Exactly one of forward, include, or
    * type must be specified.
    */
    protected String forward = null;

    /**
    * Context-relative path of the web application resource that will process
    * this request via RequestDispatcher.include(), instead of instantiating
    * and calling the Action class specified by "type".
    * Exactly one of forward, include, or
    * type must be specified.
    */
    protected String include = null;

    /**
    * Context-relative path of the input form to which control should be
    * returned if a validation error is encountered. Required if "name"
    * is specified and the input bean returns validation errors.
    */
    protected String input = null;

    /**
    * Fully qualified Java class name of the
    * MultipartRequestHandler implementation class used to
    * process multi-part request data for this Action.
    */
    protected String multipartClass = null;

    /**
    * Name of the form bean, if any, associated with this Action.
    */
    protected String name = null;

    /**
    * General purpose configuration parameter that can be used to pass
    * extra iunformation to the Action instance selected by this Action.
    * Struts does not itself use this value in any way.
    */
    protected String parameter = null;

    /**
    * Context-relative path of the submitted request, starting with a
    * slash ("/") character, and omitting any filename extension if
    * extension mapping is being used.
    */
    protected String path = null;

    /**
    * Prefix used to match request parameter names to form ben property
    * names, if any.
    */
    protected String prefix = null;

    /**
    * Comma-delimited list of security role names allowed to request
    * this Action.
    */
    protected String roles = null;

    /**
    * Identifier of the scope ("request" or "session") within which
    * our form bean is accessed, if any.
    */
    protected String scope = "session";

    /**
    * Suffix used to match request parameter names to form bean property
    * names, if any.
    */
    protected String suffix = null;

    /**
    * Fully qualified Java class name of the Action class
    * to be used to process requests for this mapping if the
    * forward and include properties are not set.
    * Exactly one of forward, include, or
    * type must be specified.
    */
    protected String type = null;

    /**
    * Should the validate() method of the form bean associated
    * with this action be called?
    */
    protected boolean validate = true;
    }

    其實ActionConfig是一個很典型的ValueObject.所以其他的get/set方法我就不寫出來了。
    看這個代碼一定要和struts-config.xml一起來看,根據struts-config.xml去找找
    每一段配置文件最終要生成一個ActionConfig,他們之間的對應關系。
    如果你想擴展Struts,ActionMapping估計你一定要修改。還有ActionServlet你也要修改。

    六:結束語
    分析了一些代碼下面做一些概述。先來整體的了解一下Struts的工作流程.
    在實現一個基于Struts的運用之前我們首先是做環境設置,Struts正常工作需要至少兩個
    配置文件web.xml,struts-config.xml.
    web.xml告訴App Server所有以.do結尾的請求最終提交給ActionServlet去處理。
    2就規定ActionServlet是在App Server啟動的時候
    創建的并且一直存在。
    ActionServlet在創建的時候會做如下的工作:
    保存一些后面需要使用的實例在Attribute(內存)里面。
    根據web.xml的配置解析struts-config.xml文件。
    根據struts-config.xml的配置生成ActionMapping實例并且保存。

    ActionServlet在生命周期就一直等待Http 請求
    每一個.do結尾的Http 請求都由ActionServlet先截獲然后根據請求路徑得到具體調用那
    一個Action去處理,在這之前生成、處理ActionForm。具體知道那一個Action去處理請求
    后調用Action的execute()/perform()處理完成,返回。


    ?

    posted @ 2006-09-13 20:23 ericli 閱讀(1392) | 評論 (0)編輯 收藏

    Toad中出現問題

    ?toad連接出現問題:
    可能是一些環境變量被修改了,比如昨天我碰到的問題
    d:\oracle\ora92\BIN 被修改了,在path 里面將其配置好,就可以了
    正常的配置信息如下:
    ?(Oracle Root)
    ? ORACLE_HOME = d:\oracle\ora92
    ? ORACLE_SID =
    ? NLS_LANG = NA
    ? SQLPATH =
    ? d:\oracle\ora92\BIN is in system PATH
    ? d:\oracle\ora92\BIN does exist
    ? Client dll found oci.dll
    ? oci.dll version: 9.2.0.1.0??
    ? (Oracle Root) is valid
    HOME0
    ? ORACLE_HOME_NAME = OraHome92
    ? ORACLE_HOME = d:\oracle\ora92
    ? ORACLE_SID = NHOALG
    ? NLS_LANG = SIMPLIFIED CHINESE_CHINA.ZHS16GBK
    ? SQLPATH = d:\oracle\ora92\dbs
    ? d:\oracle\ora92\BIN is in system PATH
    ? d:\oracle\ora92\BIN does exist
    ? Client dll found oci.dll
    ? oci.dll version: 9.2.0.1.0
    ? HOME0 is valid
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    同事遇到問題,toad安裝好一次后,就打不開了
    是版本的問題,換了一個版本就好了
    7.6--8.0
    ?

    posted @ 2006-09-13 20:21 ericli 閱讀(673) | 評論 (0)編輯 收藏

    Eclipse ShortCut

    ★ Eclipse 3.0 RC2 熱鍵表 (中英對照版,Default) ★

    Author:sungo
    Date:2004/06/16 (三)


    ◎閱讀說明:冒號 ( : )後的藍色標註熱鍵為Eclipse預設的標準熱鍵,空
    白即表示Eclipse並未對該項目設熱鍵;紅色標註選項表示常用或重要熱
    鍵;淡粉紅色標註選項,表示可以啟動該熱鍵的範圍。

    ◎熱鍵修改處:
    Window->Preference->Workbench->Keys

    ◎FAQ,如果沒設熱鍵的功能要如何啟動?
    方法一.自己增設熱鍵。
    方法二.熱鍵設定裡的選項,其實功能表大部分都有,可以由功能表中直接點選。

    ◎給所有在看這篇文章的朋友:
    T55555為了JavaWorld週年慶把DG2拿出來了,為了效法他的精神,所以我決定把
    我的第一次也貢獻出來,加入JavaWorld這半年來我第一次打這麼長的文章...XD
    。本來打算3.0 Release出來後再整理熱鍵表,但3.0 RC系列架構已經趨於平穩,
    Release出來也不會有多大的變動,所以就先整理了。熱鍵表所列的功能,只要您
    全部實際操作過一遍,將會為您在操作Eclipse上,帶來莫大的助益。

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

    Compare - 比較
    Copy All from Left to Right (由左向右複製全部)
    Copy All from Right to Left (由右向左複製全部)
    Copy from Left to Right (由左向右複製)
    Copy from Right to Left (由右向左複製)
    Select Next Change (選取下一個變更)
    Select Previous Change (選取上一個變更)

    CVS - Concurrent Versions System (版本控制系統)
    Checkout from CVS (由CVS檢查)

    Edit - 編輯
    Add Bookmark (新增書籤)
    Add Task (新增作業)
    Collapse (程式碼折疊) : Ctrl+鍵盤右方數字區的'-' <Editing Text>
    Content Assist (內容輔助 - Code Templetes啟動): Alt+/ 或 Ctrl+Space <In Dialogs and Windows>
    Context Information (內容資訊) : Alt+? 或 ALT+Shift+?或 Ctrl+Shift+Space <In Windows>
    Copy (複製選取文字到OS剪貼簿) : Ctrl+C <In Dialogs and Windows>
    Custom Encoding (自訂編碼)
    Cut (剪下選取文字並加至OS剪貼簿) : Ctrl+X <In Dialogs and Windows>
    Default Encoding (使用預設編碼)
    Delete (刪除選取的文字) : Delete <In Windows>
    Expand (程式碼展開) : Ctrl+鍵盤右方數字區的'+' <Editing Text>
    Expand All (程式碼全部展開) : Ctrl+鍵盤右方數字區的'*' <Editing Text>
    Find and Replace (尋找並取代文字) : Ctrl+F <In Windows>
    Find Next (尋找下一個項目) : Ctrl+K <Editing Text>
    Find Previous (尋找上一個項目) : Ctrl+Shift+K <Editing Text>
    Incremental Find (漸進式尋找) : Ctrl+J <Editing Text>
    Incremental Find Reverse (逆向漸進式尋找) : Ctrl+Shift+J <Editing Text>
    ISO-8859-1 Encoding (將編碼變更為 ISO-8859-1)
    Paste (從OS剪貼簿貼上文字) : Ctrl+V <In Dialogs and Windows>
    Quick Diff Toggle (QuickDiff 開啟/關閉) : Ctrl+Shift+Q <Editing Text>
    Quick Fix (快速套件修正) : Ctrl+1 <Editing Java Source>
    Redo (重做上一次作業) : Ctrl+Y <In Windows>
    Restore Last Selection (恢復最後選取) : Alt+Shift+方向鍵'↓' <Editing Java Source>
    Revert to Saved (回復至已儲存)
    Select All (選擇全部文字) : Ctrl+A <In Dialogs and Windows>
    Select Enclosing Element : (選取含括的元素) Alt+Shift+方向鍵'↑' <Editing Java Source>
    Select Next Element (選取下一個元素) : Alt+Shift+方向鍵'→' <Editing Java Source>
    Select Previous Element (選取上一個元素) : Alt+Shift+方向鍵'←' <Editing Java Source>
    Shift Left (將該行文字往左移動一個縮排)
    Shift Right (將該行文字往右移動一個縮排)
    Show Tooltip Description (在游標位置顯示元素的工具提示說明) : F2 <Editing Java Source>
    System Encoding (將編碼變更為系統編碼)
    Toggle Folding (程式碼折疊、展開功能 開啟/關閉) : Ctrl+鍵盤右方數字區的'/' <Editing Text>
    Toggle Insert Model (Smart Insert模式 開啟/關閉) : Ctrl+Shift+Insert <Editing Text>
    Undo (復原前次作業) : Ctrl+Z <In Windows>
    US ASCII Encoding (將編碼變更為 ASCII)
    UTF-16BE Encoding (將編碼變更為 UTF-16BE)
    UTF-16 Encoding (將編碼變更為 UTF-16)
    UTF-16LE Encoding (將編碼變更為 UTF-16LE)
    UTF-8 Encoding (將編碼變更為 UTF-8)

    File - 檔案
    Close (關閉檔案) : Ctrl+W 或 Ctrl+F4 <In Windows>
    Close All (關閉全部檔案) : Ctrl+Shift+W 或 Ctrl+Shift+F4 <In Windows>
    Exit (關閉螢幕最上層視窗) : Alt+F4 <In Dialogs and Windows>?? 0
    (註:3.0RC2並沒預設這組熱鍵,但仍然可以使用。)

    Export (開啟匯出功能表)
    Import (開啟匯入功能表)
    Move (移動檔案)
    New (開啟檔案建立精靈Wizard) : Ctrl+N <In Windows>
    New menu (顯示File->New選單) : ALT+Shift+N <In Windows>
    Open External File (開啟外部檔案)
    Open Workspace (開啟Workspace設定視窗)
    Print (列印檔案) : Ctrl+P <In Windows>
    Properties (org.eclipse.ui.file.properties) (顯示檔案內容) : Alt+Enter <In Windows>
    Refresh (重新整理) : F5 <In Windows>
    Rename (重新命名) : F2 <In Windows>
    Revert (回復至已儲存)
    Save (儲存檔案) : Ctrl+S <In Windows>
    Save All (儲存全部檔案) : Ctrl+Shift+S <In Windows>
    Save As (另存新檔)

    Help - 說明
    About (開啟關於對話框)
    Help Contents (開啟Eclipse說明文件)
    Tips and Tricks (開啟要訣和技巧說明頁面)
    Weclome (開啟歡迎使用頁面)

    Navigate - 導覽
    Back (向後導覽)
    Backward History (在編輯器導覽歷程中向後移動) : Alt+方向鍵'←' <In Windows>
    Forward (向前導覽)
    Forward History (在編輯器導覽歷程中向前移動) : Alt+方向鍵'→' <In Windows>
    Go Into (進入選取的目錄內)
    Go to Line (移至某一行文字) : Ctrl+L <Editing Text>
    Go to Matching Bracket (將游標移至對稱的方括弧) : Ctrl+Shift+P <Editing Java Source>
    Go to Next Member (移至下一個Member) : Ctrl+Shift+方向鍵'↓' <Editing Java Source>
    Go to Package (移至套件,用於Package Explorer)
    Go to Previous Member (移至上一個Member) : Ctrl+Shift+方向鍵'↑' <Editing Java Source>
    Go to Resource (移至資源)
    Go to Type (移至類別,用於Package Explorer)
    Last Edit Loaction (移至前次編輯位置) : Ctrl+Q <In Windows>
    Next (移至下一個標示元素) : Ctrl+. <In Windows>
    (註:元素類型可由Toolbar的Next Annotation小倒三角圖示設定。)

    Open Call Hierarchy (開啟Call Hierarchy視窗) : Ctrl+Alt+H <In Windows>
    Open Declaration (瀏覽所選取的Java元素) : F3 <In Windows> (註:效果等於Ctrl+滑鼠左鍵點選。)
    Open External Javadoc (開啟外部Javadoc) : Shift+F2 <In Windows>
    Open Resource (開啟資源選取對話方塊) : Ctrl+Shift+R <In Windows>
    Open Structure (顯示所選元素的結構) : Ctrl+F3 <Editing Java Source>
    Open Super Implementation (開啟super類型中的實作)
    Open Type (開啟類別) : Ctrl+Shift+T <In Windows>
    Open Type Hierarchy (開啟類別階層顯示視窗) : F4 <In Windows>
    Open Type in Hierarchy (在類別階層的視圖中開啟類別) : Ctrl+Shift+H <In Windows>
    Previous (移至上一個標示元素) : Ctrl+, <In Windows>
    (註:元素類型可由Toolbar的Previous Annotation小倒三角圖示設定。)

    Quick Hierarchy (以浮動方式將類別階層視窗顯示在編輯器上) : Ctrl+T <Editing Java Source>
    Quick Outline (以浮動方式將概要視窗顯示在編輯器上) : Ctrl+O <Editing Java Source>
    Show In menu (顯示當前Show In功能表可用的選項) : Alt+Shift+W <In Windows>
    Show in Package Explorer (在套件瀏覽器中顯示所選元素)
    Up (導覽上一層)

    Project - 專案
    Build All (建置所有專案) : Ctrl+B <In Windows>
    Build Clean (清除專案)
    Build Project (建置專案)
    Close Project (關閉專案)
    Generate Javadoc (產生Javadoc)
    Open Project (開啟專案)
    Properties (org.eclipse.ui.project.properties) (開啟專案屬性設定視窗)
    Rebuild All (重新建置所有專案)
    Rebuild Project (重新建置專案)
    Repeat Working Set Build (重複建置所設定的專案) (註:Build Automatically 關閉時才可使用。)

    Refactor - Java (重構 - Java)
    Change Method Signature (變更方法簽章) : Alt+Shift+C <In Windows>
    Convert Anonymous Class to Nested (將匿名類別轉換成巢狀類別)
    Convert Local Variable to Field (將區域變數轉換成欄位) : Alt+Shift+F <Editing Java Source>
    Encapsulate Field (封裝欄位:為欄位建立getting和setting方法,並只用這些方法來存取欄位)
    Extract Constant (擷取成常數:將數字擷取至新的Static欄位,並使用新的Static欄位)

    註:<-START->

    如下段程式碼經由Extract Constant重構數字10後...
    12345
    ?public class Test {
    ??? public static void main(String[] args) {
    ??????? int x = 10;
    ??? }
    }

    ?
    會變成下列程式碼:(常數欄位名稱,在重構時可以自由設定。)123456
    ?public class Test {
    ??? public static final int TEN = 10;
    ??? public static void main(String[] args) {
    ??????? int x = TEN;
    ??? }
    }

    ?
    註:<-END->

    Extract Interface (擷取成介面:將原類別內的方法擷取至新介面中,原類別將實作該介面)
    (註:新介面會存成一個新的*.java檔。若是在interface中執行此功能,舊介面則會繼承新介面。)
    Extract Local Variable (擷取成區域變數:將數字擷取為新的區域變數) : Alt+Shift+L <In Windows>
    Extract Method (擷取成方法:將選取的表示式擷取成一個新方法) : Alt+Shift+M <In Windows>
    Generalize Type (將reference的類別型態更改可以取代的Superclass)
    Inline (列入常數、區域變數或方法) : Alt+Shift+I <In Windows>
    Introduce Factory (採用代理:利用方法來取得建構子)

    註:<-START->

    如下段程式碼經由Introduce Factory重構Test建構子後...
    123456789
    ?public class Test {
    ??? private int number;
    ??? Test(int x) {
    ??????? number = x;
    ??? }
    ??? public static void main(String[] args) {
    ??????? System.out.println(new Test(5).number);
    ??? }
    }

    ?
    會變成下列程式碼:123456789101112
    ?public class Test {
    ??? private int number;
    ??? public Test(int x) {
    ??????? number = x;
    ??? }
    ??? public static void main(String[] args) {
    ??????? System.out.println(createTest(5).number);
    ??? }
    ??? public static Test createTest(int x) {
    ??????? return new Test(x);
    ??? }
    }

    ?
    註:<-END->

    Introduce Parameter (採用參數:將區域變數改成參數方式傳遞)

    註:<-START->

    如下段程式碼經由Introduce Parameter重構數字5後...
    12345
    ?public class Test {
    ??? public static void main(String[] args) {
    ??????? int x = 5;
    ??? }
    }

    ?
    會變成下列程式碼:12345
    ?public class Test {
    ??? public static void main(String[] args, int five) {
    ??????? int x = five;
    ??? }
    }

    ?
    註:<-END->

    Move Member Type to New File (將類別成員移至一個新檔)
    Move - Refactoring (移動 - 重構:將所選取的元素移至新位置) : Alt+Shift+V <In Windows>
    Pull Up (將類別成員<欄位與方法>上推到類別的父類別中)
    Push Down (將類別成員(欄位與方法)下推到類別的子類別中)
    Redo - Refactoring (重做 - 重構:重做前次的重構) : Alt+Shift+Y <In Windows>
    Refactor Quick Menu (在編輯區顯示重構的快速功能表) : Alt+Shift+T <In Windows>
    Rename - Refactoring (更名 - 重構:將所選取的元素重新命名,類別名稱、區域變數名稱等...) :
    Alt+Shift+R <In Windows>
    Undo - Refactoring (復原 - 重構:復原前次的重構) : Alt+Shift+Z <In Windows>
    Use Supertype Where Possible (啟動「適當時使用父類別」重構對話框。)

    ◎補充命名規則:(重構時不照此規則命名時,Eclipse將會警示,
    雖然可以不管警示,但這是個好風格。)

    1.介面(interface)名稱:開頭大寫。
    2.區域變數(Local Variable)名稱:開頭小寫 。
    3.常數欄位(public static final int...)名稱:全部大寫。

    Run/Debug - 執行/除錯
    Add Class Load Breakpoint (新增一個類別載入中斷點))
    Add Java Exception Breakpoint (新增一個Java異常狀況中斷點)
    Debug... (開啟除錯啟動配置對話框)
    Debug Last Launched (開啟最近一次啟動作業的除錯模式) : F11 <In Windows>
    Display (org.eclipse.jdt.debug.ui.commands.Display) (顯示) : Ctrl+Shift+D <In Windows>
    (註:當執行緒暫停時,此指令會使用「顯示」檢視畫面,顯示在該執行緒之堆疊框或變數的環境定義下
    ,評估所選表示式的結果。)

    Execute (執行:開啟執行啟動配置對話框) : Ctrl+U <In Windows>
    Inspect (觀察): Ctrl+Shift+I <In Windows>
    (註:當執行緒暫停時,此指令會使用「表示式」檢視畫面,顯示在該執行緒之堆疊框或變數的環境定義
    下,視察所選表示式或變數的結果。)

    Profile Last Launched (最近一次作業的概況)
    Resume (繼續執行緒的執行) : F8 <Debugging>
    Run Last Launched (在執行模式下迅速執行最近一次的啟動作業): Ctrl+F11 <In Windows>
    Run Last Launched External Tool (執行前一次啟動的外部工具)
    Run to Line (執行至指定行,可在沒有設定中斷點之處暫停執行) : Ctrl+R <Debugging>
    Skip All Breakpoints (在不清除中斷點的情況下,執行時跳過所有的中斷點)
    Step Into (進入副程序) : F5 <Debugging>
    Step Into Selection (進入目前所選的陳述式進行副程序除錯) : Ctrl+F5 <Debugging>
    Step Over (跳過副程序) : F6 <Debugging>
    Step Return (跳出副程序): F7 <Debugging>
    Suspend (暫停執行緒)
    Terminate (終止執行緒)
    Toggle Breakpoint (新增/移除,中斷點) : Ctrl+Shift+B <In Windows>
    Toggle Method Breakpoint (新增/移除,方法中斷點)
    Toggle Step Filters (以過濾條件逐步除錯) : Shift+F5 <In Windows>
    Toggle Watchpoint (新增/移除,欄位的監視點)

    Search - 搜索
    Declaration in Hierarchy (在它的階層中搜尋所選元素的宣告)
    Declaration in Project (在專案中搜尋所選元素的宣告)
    Declaration in Working Set (在工作集中搜尋所選元素的宣告)
    Declaration in Workspace (在工作區中搜尋所選元素的宣告) : Ctrl+G <In Windows>
    Exception Occurrences (搜索例外事件)
    File Search (開啟搜尋對話框的檔案搜尋頁面)
    Implementors in Project (在專案中搜尋所選介面的實作者)
    Implementors in Working Set (在工作集中搜尋所選介面的實作者)
    Implementors in Workspace (在工作區中搜尋所選介面的實作者)
    Occurrences in File (在它的宣告檔案中搜尋所選元素的所有出現處) : Ctrl+Shift+U <In Windows>
    Open Search Dialog (開啟搜尋對話框) : Ctrl+H <In Windows>
    Read Access in Hierarchy (在它的階層中搜尋所選元素的讀取參考)
    Read Access in Project (在專案中搜尋所選元素的讀取參考)
    Read Access in Working Set (在工作集中搜尋所選元素的讀取參考)
    Read Access in Workspace (在工作區中搜尋所選元素的讀取參考)
    References in Hierarchy (在它的階層中搜尋所選元素的參考)
    References in Project (在專案中搜尋所選元素的參考)
    References in Working Set (在工作集中搜尋所選元素的參考)
    References in Workspace (在工作區中搜尋所選元素的參考) : Ctrl+Shift+G <In Windows>
    Referring Tests (查詢測試)
    Write Access in Hierarchy (在它的階層中搜尋所選元素的寫入參考)
    Write Access in Project (在專案中搜尋所選元素的寫入參考)
    Write Access in Working Set (在工作集中搜尋所選元素的寫入參考)
    Write Access in Workspace (在工作區中搜尋所選元素的寫入參考)

    Source - 程式碼
    Add Block Comment (將選取的字行以多行註解/**/包起來) : Ctrl+Shift+/ <Editing Java Source>
    Add Constructors from Superclass (從父類別增加一個建構子)
    Add Import (為目前所選的類別參考建立一項匯入宣告) : Ctrl+Shift+M <Editing Java Source>
    Add Javadoc Comment (新增Javadoc註解) : Alt+Shift+J <In Windows>
    Comment (註解)
    Externalize Strings (開啟「外部化字串」精靈)
    Find Strings to Externalize (尋找要外部化的字串)
    Format (程式碼自動排版) : Ctrl+Shift+F <Editing Java Source>
    Format Element (格式化元素)
    Generate Constructor using Fields (使用欄位來產生建構子)

    註:<-START->

    如下段程式碼,選取欄位名稱money並經由Generate Constructor using Fields指令後...
    12345
    ?public class Test {
    ??? int money;
    ??? public static void main(String[] args) {
    ??? }
    }

    ?
    會變成下列程式碼:12345678
    ?public class Test {
    ??? int money;
    ??? public Test(int money) {
    ??????? this.money = money;
    ??? }
    ??? public static void main(String[] args) {
    ??? }
    }

    ?
    註:<-END->

    Generate Delegate Methods (開啟「產生委派方法」對話框,可新增類型欄位的委派方法)
    Generate Getters and Setters (開啟「產生Getter與Setter」對話框,可以為欄位自動
    建立Getter和Setter方法)
    Indent Line (單行縮排,其會遵照Formatter設定的格式) : Ctrl+I <Editing Java Source>
    Mark Occurrences (標註事件): Alt+Shift+O <Editing Java Source>
    Organize Imports (組織匯入) : Ctrl+Shift+O <In Windows>
    (註:這是個很方便的功能,簡易說明一下使用時機:假設我們在程式中打,JFrame src;而並未
    import任何swing類別,此時Eclipse便會出現錯誤警示,用紅底線將JFrame標起來,此時只要按
    下Ctrl+Shift+O,Eclipse便會自動將:import javax.swing.JFrame;加到程式碼中了。)

    Override/Implement Methods (開啟「覆寫/實作方法」對話框,可覆寫或實作現行類別中的方法)
    Remove Block Comment (移除多行註解/**/) : Ctrl+Shift+\ <Editing Java Source>
    Remove Occurrence Annotations (移除事件書籤): Alt+Shift+U <Editing Java Source>
    Sort Members (排序成員)
    Source Quick Menu (在編輯區顯示Source的快速功能表) : Alt+Shift+S <In Windows>
    Surround with try/catch Block (以try/catch區塊包覆所選文字)
    Toggle Comment (加上單行註解/取消單行註解) : Ctrl+/ 或 Ctrl+7 或 Ctrl+Shift+C
    <Editing Java Source>
    Uncomment (取消註解)

    ◎補充,Source 隱藏熱鍵:
    1.Shift Right (向右移位,增加目前所選字行的內縮層次) : Tab <Editing Java Source>
    2.Shift Left (向左移位,減少目前所選字行的內縮層次) : Shift+Tab <Editing Java Source>

    Team - 團隊
    Synchronize (同步化)

    Text Editing - 文字編輯
    Claer Mark (清除標記)
    Copy Lines (將選取的文字,複製成新行) : Ctrl+Alt+方向鍵'↓' <Editing Text>
    Cut Line (剪下單行文字)
    Cut to Beginning of Line (剪下文字,範圍為選取處至單行開頭)
    Cut to End of Line (剪下文字,範圍為選取處至單行尾端)
    Delete Line (刪除單行文字) : Ctrl+D <Editing Text>
    Delete Next (刪除下一行)
    Delete Next Word (刪除下一個字組) : Ctrl+Delete <Editing Text>
    Delete Previous (刪除前一行)
    Delete Previous Word (刪除前一個字組) : Ctrl+Backspace <Editing Text>
    Delete to Beginning of Line (刪除文字,範圍為選取處至單行開頭)
    Delete to End of Line (刪除文字,範圍為選取處至單行尾端)
    Duplicate Lines (將選取的文字,複製成新行) : Ctrl+Alt+方向鍵'↑' <Editing Text>
    Insert Line Above Current Line (在游標處的該行上方插入新行) : Ctrl+Shift+Enter <Editing Text>
    Insert Line Below Current Line (在游標處的該行下方插入新行) : Shift+Enter <Editing Text>
    Line Down (游標往下移一行)
    Line End (游標移至該行尾端)
    Line Start (游標移至該行開頭)
    Line Up (游標往上移一行)
    Move Lines Down (將該行文字往下移動) : Alt+方向鍵'↓' <Editing Text>
    Move Lines Up (將該行文字往上移動) : Alt+方向鍵'↑' <Editing Text>
    Next Column (游標移至下一列)
    Next Word (游標移至下一個字組) : Ctrl+方向鍵'→' <Editing Text>
    Page Down (移至下一頁)
    Page Up (移至上一頁)
    Previous Column (游標移至上一列)
    Previous Word (游標移至上一個字組) : Ctrl+方向鍵'←' <Editing Text>
    Scroll Line Down (向下捲動) : Ctrl+方向鍵'↓' <Editing Text>
    Scroll Line Up (向上捲動) : Ctrl+方向鍵'↑' <Editing Text>
    Select Line Down (選取下一行)
    Select Line End (選取至文字尾端)
    Select Line Start (選取至文字開頭)
    Select Line Up (選取上一行)
    Select Next Column (選取下一列)
    Select Next Word (選取下一個字組): Ctrl+Shift+方向鍵'→' <Editing Text>
    Select Page Down (選取下一頁)
    Select Page Up (選取上一頁)
    Select Previous Column (選取上一列)
    Select Previous Word (選取前一個字組) : Ctrl+Shift+方向鍵'←' <Editing Text>
    Select Text End (選取至文字編輯器尾端)
    Select Text Start (選取至文字編輯器開頭)
    Select Window End (選取至視窗尾端)
    Select Window Start (選取至視窗開頭)
    Set Mark (設定標記)
    Swap Mark (交換標記)
    Text End (游標移至文字編輯器最底端)
    Text Start (游標移至文字編輯器最頂端)
    Toggle Overwrite (覆寫/插入 模式選擇) : Insert <Editing Text>
    To Lower Case (將選取的英文字轉為小寫) : Ctrl+Shift+Y <Editing Text>
    To Upper Case (將選取的英文字轉為大寫) : Ctrl+Shift+X <Editing Text>
    Window End (將游標移至視窗尾端)
    Window Start (將游標移至視窗開頭)

    Views - 檢視
    Ant (開啟Ant檢視視窗)
    Bookmarks (開啟書籤檢視視窗)
    Breakpoints (開啟中斷點檢視視窗)
    Classic Search (開啟傳統的搜索檢視視窗)
    Console (開啟主控臺檢視視窗)
    CVS Annotate (開啟CVS Annotate檢視視窗)
    CVS Editors (開啟CVS Editor檢視視窗)
    CVS Repositories (開啟CVS Repositories檢視視窗)
    CVS Resource History (開啟CVS Resource History檢視視窗)
    Debug (開啟除錯檢視視窗)
    Display (org.eclipse.jdt.debug.ui.DisplayView) (開啟除錯-顯示檢視視窗)
    Error Log (開啟錯誤記錄檢視視窗)
    Expressions (開啟除錯-表示式檢視視窗)
    Java Call Hierarchy (開啟Call Hierarchy檢視視窗)
    Java Declaration (開啟宣告檢視視窗)
    Javadoc (開啟Javadoc檢視視窗)
    Java Members (開啟類別成員檢視視窗)
    Java Package Explorer (開啟套件瀏覽器) : Alt+Shift+Q,P <In Windows>
    Java Packages (開啟Java套件檢視視窗)
    Java Projects (開啟Java專案檢視視窗)
    Java Type Hierarchy (開啟類別階層檢視視窗) : Alt+Shift+Q,T <In Windows>
    Java Types (開啟Java類別檢視視窗)
    JUnit (開啟JUnit檢視視窗)
    Memory (開啟除錯-記憶體檢視視窗)
    Navigator (開啟導覽器)
    Outline (開啟概要檢視視窗) : Alt+Shift+Q,O <In Windows>
    Plug-in Dependencies (開啟Plug-in Dependencies檢視視窗)
    Plug-in Registry (開啟Plug-in Registry檢視視窗)
    Plug-ins (開啟Plug-ins檢視視窗)
    Problems (開啟問題檢視視窗) : Alt+Shift+Q,X <In Windows>
    Progress (開啟執行進度檢視視窗)
    Properties (org.eclipse.ui.views.Property/Sheet) (開啟屬性檢視視窗)
    Registers (開啟除錯-暫存器檢視視窗)
    Search (開啟搜索檢視視窗) : Alt+Shift+Q,S <In Windows>
    Synchronize (開啟同步化檢視視窗) : Alt+Shift+Q,Y <In Windows>
    Tasks (開啟作業檢視視窗)
    Threads and Monitors (開啟除錯-執行緒檢視視窗)
    Variables (開啟除錯-變數檢視視窗)

    ◎補充:Views 檢視視窗的開啟處:
    Window->Show View->Other。

    Window - 視窗
    Activate Editor (啟動編輯器) : F12 <In Windows>
    Close All Perspectives (關閉全部視景)
    Close Perspective (關閉視景)
    Customize Perspective (自訂視景)
    Hide Editors (隱藏編輯器)
    Lock the Toolbars (鎖定工具列)
    Maximize Active View or Editor (編輯區最大化) : Ctrl+M <In Windows>
    Next Editor (切換至下一個編輯器) : Ctrl+F6 <In Windows>
    Next Perspective (切換至下一個視景) : Ctrl+F8 <In Windows>
    Next View (切換至下一個視圖) : Ctrl+F7 <In Windows>
    Open Editor Drop Down (以浮動的方式在編輯區,顯示快速切換編輯器功能表) : Ctrl+E <In Windows>
    Pin Editor (固定編輯器)
    Preferences (開啟偏愛設定)
    Previous Editor (切換至上一個編輯器) : Ctrl+Shift+F6 <In Windows>
    Previous Perspective (切換至上一個視景) : Ctrl+Shift+F8 <In Windows>
    Previous View (切換至上一個視圖) : Ctrl+Shift+F7 <In Windows>
    Reset Perspective (重新設定視景)
    Save Perspective As (儲存為新視景)
    Show Ruler Context Menu (顯示尺規的內容功能表) : Ctrl+F10 <Editing Text>
    Show Selected Element Only (僅顯示所選元素的程式碼)
    Show System Menu (顯示系統功能表) : Alt+- <In Windows>
    Show View Menu (顯示視圖功能表) : Ctrl+F10 <In Windows>
    Switch to Editor (切換至編輯器) : Ctrl+Shift+E <In Windows>

    posted @ 2006-09-13 20:20 ericli 閱讀(1480) | 評論 (0)編輯 收藏

    J2EE開發之常用開源項目介紹--轉載(學習)

    主要還是以Spring為核心,也總結了一些以前web開發常用的開源工具和開源類庫
    ?
    1持久層:???????
    1)Hibernate
    這個不用介紹了,用的很頻繁,用的比較多的是映射,包括繼承映射和父子表映射
    對于DAO在這里介紹個在它基礎上開發的包bba96,目前最新版本是bba96 2.0它對Hibernate進行了封裝, 查詢功能包括執行hsql或者sql查詢/更新的方法,如果你要多層次邏輯的條件查詢可以自己組裝QueryObject.可以參考它做HibernateDAO.也可以直接利用它
    2) iBATIS
    另一個ORM工具,沒有Hibernate那么集成,自由度比較大,所以使用時普遍性能上比Hibernate要快一些.
    2:SpringMVC
    ?????? 原理說明和快速入門:
    ?????? 配置文件為:
    Spring的配置文件默認為WEB-INF/xxxx-servelet.xm其中xxx為web.xml中org.springframework.web.servlet.DispatcherServlet的servlet-name。
    ?????? Action分發:
    Spring將按照配置文件定義的URL,Mapping到具體Controller類,再根據URL里的action= xxx或其他參數,利用反射調用Controller里對應的Action方法。
    輸入數據綁定:
    Spring提供Binder 通過名字的一一對應反射綁定Pojo,也可以直接從request.getParameter()取數據。
    輸入數據驗證
    Sping 提供了Validator接口當然還可以使用開源的Commons-Validaor支持最好
    Interceptor(攔截器)
    Spring的攔截器提供接口需要自己編寫,在這點不如WebWork做的好.全面
    ?????? (這里提一下WebWork和Struts的區別最主要的區別在于WebWork在建立一個Action時是新New一個對象而Struts是SingleMoule所有的都繼承它的一個Action,所以根據項目需要合適的選擇.)
    3:View層
    1) 標簽庫:JSP2.0/JSTL
    由于Webwork或Spring的標簽確實很有限,一般view層用JSTL標簽,而且據說JSTL設計很好速度是所有標簽中最快的使用起來也很簡單
    ?
    2) 富客戶端:DOJO Widgets, YUI(YahooUI),FCKEditor, Coolest日歷控件
    Dojo主要提供Tree, Tab等富客戶端控件,可以用其進行輔助客戶端開發
    YahooUI和DOJO一樣它有自己的一套javascript調試控制臺,主要支持ajax開發也有很多Tree,Table,Menu等富客戶端控件
    FCKEditor 最流行的文本編輯器
    Coolest日歷控件 目前很多日歷控件可用,集成在項目中也比較簡單,這個只是其中的一個,界面不錯的說..
    ?
    3) JavaScript:Prototype.js
    Prototype.js作為javascript的成功的開源框架,封裝了很多好用的功能,通過它很容易編寫AJAX應用,現在AJAX技術逐漸成熟,框架資源比較豐富,比如YUI,DWR等等,也是因為JavaScript沒有合適的調試工具,所以沒有必要從零開始編寫AJAX應用,個人認為多用一些成熟的Ajax框架實現無刷新更新頁面是不錯的選擇.
    ?
    4)表格控件:Display Tag ,Extreme Table
    這兩個的功能差不多,都是View層表格的生成,界面也比較相向,可以導出Excel,Pdf,對Spring支持很容易.
    相比較而言比較推薦ExtremeTable,它的設計很好功能上比DisplayTag多一些,支持Ajax,封裝了一些攔截器,而且最方面的是在主頁wiki中有詳細的中文使用文檔.
    ?
    5):OSCache
    OSCache是OpenSymphony組織提供的一個J2EE架構中Web應用層的緩存技術實現組件,Cache是一種用于提高系統響應速度、改善系統運行性能的技術。尤其是在Web應用中,通過緩存頁面的輸出結果,可以很顯著的改善系統的穩定性和運行性能。
    它主要用在處理短時間或一定時間內一些數據或頁面不會發生變化,或將一些不變的統計報表,緩沖在內存,可以充分的減輕服務器的壓力,防治負載平衡,快速重啟服務器(通過硬盤緩存).
    ?
    6)SiteMesh
    sitemesh應用Decorator模式主要用于提高頁面的可維護性和復用性,其原理是用Filter截取request和response,把頁面組件head,content,banner結合為一個完整的視圖。通常我們都是用include標簽在每個jsp頁面中來不斷的包含各種header, stylesheet, scripts and footer,現在,在sitemesh的幫助下,我們刪掉他們輕松達到復合視圖模式.
    Sitemesh也是 OpenSymphony的一個項目現在最近的版本是2.2,目前OpenSymphony自從04年就沒有更新的版本了..感覺它還是比較有創新的一種頁面組裝方式, OpenSymphony開源組織的代碼一般寫的比較漂亮,可以改其源代碼對自己的項目進行適配.
    測試發現Sitemesh還存在一些問題,比如中文問題,它的默認編碼是iso-8859-1在使用時候需要做一些改動.
    ?
    7)CSS,XHTML
    這個不用說了,遵循W3C標準的web頁面開發.
    ?
    8)分頁標簽: pager-taglib組件
    Pager-taglib 是一套分頁標簽庫,可以靈活地實現多種不同風格的分頁導航頁面,并且可以很好的與服務器分頁邏輯分離.使用起來也比較簡單.
    ?
    9)Form: Jodd Form taglib
    Jodd Form taglib使用比較簡單,只要把<form>的頭尾以<jodd:form bean= "mybean">包住
    就會自動綁定mybean, 自動綁定mybean的所有同名屬性到普通html標記input, selectbox, checkbox,radiobox.....在這些input框里不用再寫任何代碼…
    ??????
    10)Ajax:DWR
    ?????? J2EE應用最常用的ajax框架
    ??????
    ?????? 11)報表 圖表
    Eclipse BIRT功能比較強大,也很龐大..好幾十M,一般沒有特別需求或別的圖表設計軟件可以解決的不用它
    JasperReports+ iReport是一個基于Java的開源報表工具,它可以在Java環境下像其它IDE報表工具一樣來制作報表。JasperReports支持PDF、HTML、XLS、CSV和XML文件輸出格式。JasperReports是當前Java開發者最常用的報表工具。
    JFreeChart主要是用來制作各種各樣的圖表,這些圖表包括:餅圖、柱狀圖(普通柱狀圖以及堆棧柱狀圖)、線圖、區域圖、分布圖、混合圖、甘特圖以及一些儀表盤等等。
    ??????
    ?
    4:權限控制: Acegi
    Acegi是Spring Framework 下最成熟的安全系統,它提供了強大靈活的企業級安全服務,如完善的認證和授權機制,Http資源訪問控制,Method 調用訪問控制等等,支持CAS
    (耶魯大學的單點登陸技術,這個單點登陸方案比較出名.我也進行過配置使用,可以根據項目需要,如果用戶分布在不同的地方不同的系統通用一套登陸口令可以用它進行解決,一般注冊機登陸機就是這樣解決的)
    ?????? Acegi只是于Spring結合最好的安全框架,功能比較強大,當然還有一些其他的安全框架,這里列舉一些比較流行的是我從網上找到的,使用方法看其官方文檔把…
    JAAS, Seraph, jSai - Servlet Security, Gabriel, JOSSO, Kasai, jPAM, OpenSAML都是些安全控制的框架..真夠多的呵呵
    ?
    5:全文檢索
    ?????? 1) Lucene
    ?????? Lucene是一套全文索引接口,可以通過它將數據進行倒排文件處理加入索引文件,它的索引速度和查詢速度是相當快的,查詢百萬級數據毫秒級出結果,現在最火的Apache開源項目,版本更新速度很快現在已經到了2.0,每個版本更新的都比較大,目前用的最多的版本應該是1.4.3,但它有個不太方面的地方單個索引文件有2G文件限制,現在2.0版本沒有這個限制,我研究的比較多,它的擴展性比較好,可以很方面的擴充其分詞接口和查詢接口.
    ?????? 基于它的開發的系統很多,比如最常用的Eclipse的搜索功能,還有一些開源的軟件比如Compass,Nutch,Lius,還有我最近做的InSearch(企業級FTP文件網頁搜索)
    6:公共Util類
    ?????? 主要是Jakarta-Commons類庫,其中最常用得是以下幾個類庫
    1) Jakarta-Commons-Language
    ?????? 最常用得類是StringUtils類,提供了使用的字符串處理的常用方法效率比較高
    2) Jakarta-Commons-Beantuils
    ?????? 主要用Beantuils能夠獲得反射函數封裝及對嵌套屬性,map,array型屬性的讀取。
    3) Jakarta-Commons-Collections
    ?????? 里面有很多Utils方法
    ?
    7 日志管理
    ?????? Log4J
    ?????? 任務是日志記錄,分為Info,Warn,error幾個層次可以更好的調試程序
    ?
    8 開源的J2EE框架
    ?????? 1) Appfuse
    ????????????? Appfuse是Matt Raible 開發的一個指導性的入門級J2EE框架, 它對如何集成流行的Spring、Hibernate、iBatis、Struts、Xdcolet、JUnit等基礎框架給出了示范. 在持久層,AppFuse采用了Hibernate O/R映射工具;在容器方面,它采用了Spring,用戶可以自由選擇Struts、Spring/MVC,Webwork,JSF這幾個Web框架。
    ??????
    ?????? 2) SpringSide
    ?????? .SpringSide較完整的演示了企業應用的各個方面,是一個電子商務網站的應用 SpringSide也大量參考了Appfuse中的優秀經驗。最重要的是它是國內的一個開源項目,可以了解到國內現在的一些實際技術動態和方向很有指導意義…
    ?
    9:模版 Template
    主要有Veloctiy和Freemarker
    模板用Servlet提供的數據動態地生成 HTML。編譯器速度快,輸出接近靜態HTML???????????? 頁面的速度。
    ?
    10:工作流
    ?????? 我所知道比較出名的主要有JBpm Shark Osworkflow,由于對它沒有過多的研究所以還不是很清楚之間有什么區別.
    ?
    項目管理軟件
    dotProject:是一個基于LAMP的開源項目管理軟件。最出名的項目管理軟件
    JIRA: 項目計劃,任務安排,錯誤管理
    Bugzilla:提交和管理bug,和eclipse集成,可以通過安裝MyEclipse配置一下即可使用
    BugFree借鑒微軟公司軟件研發理念、免費開放源代碼、基于Web的精簡版Bug管理
    CVS:這個就不介紹了都在用.
    SVN: SubVersion已逐漸超越CVS,更適應于JavaEE的項目。Apache用了它很久后,Sourceforge剛剛推出SVN的支持。
    測試用例:主要JUnit單元測試,編寫TestCase,Spring也對Junit做了很好的支持
    ?
    后記:
    ?????? 以Spring為主的應用開發可選用的組件中間件真是眼花繚亂,所以針對不同的項目需求可以利用不同的開源產品解決,比如用Spring+Hibernate/ iBATIS或Spring+WebWork+Hibernate/ iBATIS或Spring+Struts+Hibernate/ iBATIS,合理的框架設計和代碼復用設計對項目開發效率和程序性能有很大的提高,也有利于后期的維護.

    posted @ 2006-09-13 20:19 ericli 閱讀(553) | 評論 (1)編輯 收藏

    僅列出標題  下一頁
    主站蜘蛛池模板: 亚洲免费观看在线视频| 亚洲人成高清在线播放| 国产精品久久久久免费a∨| 中国极品美軳免费观看| 欧美亚洲国产SUV| 亚洲激情校园春色| 国产亚洲一区二区三区在线| 免费一级毛片免费播放| 歪歪漫画在线观看官网免费阅读| 日韩免费的视频在线观看香蕉| 美女被吸屁股免费网站| 亚洲性色精品一区二区在线| 亚洲精品福利网泷泽萝拉| 久久久亚洲精品视频| 久久国产成人精品国产成人亚洲| 女人18毛片水真多免费看| 最近高清中文字幕无吗免费看| 99久久国产精品免费一区二区| 老外毛片免费视频播放| 亚洲成a人无码亚洲成www牛牛 | 中日韩亚洲人成无码网站| 亚洲精彩视频在线观看| 亚洲a一级免费视频| 亚洲AV无码精品无码麻豆| 国产偷国产偷亚洲清高动态图| 亚洲第一永久AV网站久久精品男人的天堂AV | 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 亚洲av女电影网| 久久综合图区亚洲综合图区| 三上悠亚亚洲一区高清| 久久精品亚洲乱码伦伦中文| 亚洲成A人片在线观看无码3D| 免费无遮挡无码永久在线观看视频| 国产精品四虎在线观看免费 | 学生妹亚洲一区二区| 亚洲精品午夜国产va久久| 亚洲色大成网站www尤物| 亚洲国产日韩a在线播放| 国产成人精品日本亚洲语音 | 女性无套免费网站在线看| 日本不卡在线观看免费v|