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

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

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

    posts - 23, comments - 0, trackbacks - 0, articles - 3
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229639  發表時間: 2008年06月19日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    經過辛苦的建站工作,網站終于建成發布了。的確,你大可以坐下來休息一下,一邊喝著咖啡一邊欣賞自己的網站,但千萬不要以為這樣就可以坐著待訂單會滾滾而來。坦率地說,倘若嚴格按照前獎期所介紹的建站方法做了,估計會有五、六成的收獲把握,不過那可能需要等待較長的時間,因為你要等著搜索引擎在眾多的網站中找到你,然后網站被搜索引擎收錄、網頁媒介標簽META(所設置的關鍵字、網頁描述等)被讀取,令排位緩慢爬升,然后瀏覽逐漸地提......。

    與上述被動式的"坐等生意"相比,筆者提倡在"精耕細作"基礎之上,主動進行網站的推廣和網絡行銷工作。事實上,網站推廣和網絡行銷是一件事物的兩個方位。網站推廣是讓更多的人知道你的網站、提高網站流量;網絡行銷是如何留住回頭客、提升成交率,兩者相輔相成,缺一不可。目前網站推廣和網絡行銷的方法歸納有:搜索引擎排名、網絡廣告、合作專題(軟廣告)、電子雜志、電子郵件行銷等。筆者認為搜索引擎行銷是企業網站宣傳推廣最值得投入的(費用不是很高),而其余的網絡行銷方式則視情況而定。

    一.搜索引擎行銷

    1.主動向搜索引擎和目錄分類站點登記注冊

    很多企業網站內容豐富,頗有創意,卻鮮有訪問者,原因何在?在于沒有進行網站的宣傳推廣工作,正如一位絕色女子,卻"養在深閨無人識"。沒有網站宣傳和網絡行銷,網站如同虛設,你就不可能達到你建設網站的目的。搜索引擎行銷的基本思想是讓用戶發現你,并點擊進去進一步了解他所需要的資訊和服務。

    還記得上期所做的工作嗎?那些網頁媒介標簽META,那些從競爭對手的網頁中找出的,根據自己的具體情況整理的,優于競爭對手的關鍵字(KEYWORDS),網頁標題(TITLE)和網頁描述(DESCRIPTION),現在是用武之地了。首先認真準備好網頁的TITLE和META標簽,以20個最重要的關鍵字為基本元素,找出與自己網頁內容相關的專業性、地區性搜索引擎和目錄站點,主動向它們登記注冊。

    由于95%的網上用戶是通過Yahoo!、Google、Altavista、Excite、Infoseek、Netscape、Hotbot、Looksmart、Lycos、MSN、All the Web、Webcrawler、AOL、Netfind、Fast、Ask Jeeves、Dmoz、About、Euroseek和Northern Light等搜索引擎來尋找他們所需要資訊,因此它們是網站登記注冊中最重要的部分,在很大程度上決定了網站宣傳推廣的成敗。

    目前,市面上專門的搜索引擎登記注冊軟體很多,號稱能自動發送到上千的搜索引擎和目錄分類網站,對此應謹慎用之。筆者強烈建議對上述全球TOP 20搜索引擎和目錄分類網站,以手工登記為上策(原因很奧妙)。在此以Altavista為例,重點介紹主要搜索引擎登記網頁的步驟和技巧。

    1)用Meta Medic檢查你的Metatag是否符合各大搜索引擎的標準;只有在通過Meta Medic的檢測后,才能進行網頁登記。(http://www.northernwebs.com/set/setsimjr.html)

    2)首先向AltaVista登記你的網站的首頁。在所有的搜索引擎中,Altavista收錄網頁的速度最快,在一至兩天內就會收錄你所申請登記的網頁。隔兩天后,在Infoseek中鍵入你的域名或網頁的標題,看Altavista是否收錄了你的網站。如果Altavista已經收錄了你的網站,鍵入關鍵字來檢查你的網頁在搜索結果的排名情況,如果排名不理想,你需要重復設置首頁中的網頁媒介標簽META。仔細閱讀Altavista中Add your page上的提示,向Altavista report your dead link,請求Altavista刪除已被收錄的網頁,然后重新登記你修改過的網頁。你需要不斷重復以上步驟,直至在Altavista的搜索結果中取得你理想的排名為止。

    3)在一個星期后,如果你的網頁在Altavista的搜索結果中的理想排名沒有大的變化,那么說明你不但通過了Altavista這一關,而且你的Metatag也不會被其他搜索引擎認為是Spamming(胡亂塞入垃圾電子郵件行為)。

    4)向其他搜索引擎登記你的網頁,要注意三點:

    嚴格遵守每個搜索引擎的規定。如Yahoo!規定網站描述不得超過20個字(包括標點符號),能在Yahoo!的搜索結果中排前10名,將會給你帶來很大效益;

    只向搜索引擎登記首頁和最重要的兩至三頁,搜索程式會根據你首頁的鏈結讀出其他頁面并收錄。建議第一次只登記首頁。

    這些搜索引擎收錄網頁的時間從幾天至幾周不等。筆者建議等待一個月后,鍵入你的域名查詢。如果網站沒有被收錄,再次登記直至被收錄為止。要注意在一個月內,千萬不要重復登記你的網頁,這也許會導致網頁永遠不會被收錄。

    12家著名中文搜索引擎推介序號網站名稱網址

    01 雅虎中文 www.yahoo.com.cn

    02 Google www.google.com

    03 新浪 www.sina.com.cn

    04 網易 www.163.com

    05 搜狐 www.sohu.com

    06 3721 www.3721.com

    07 百度 www.baidu.com

    08 tom.com www.tom.com

    09 21cn www.21cn.com

    10 263在線 www.263.net

    11 中國搜索聯盟 www.chinasearch.com.cn

    12 中文Lycos www.lycos.com.cn

    2.Google的工作原理

    Google自1998年成立至今,在短短5年間已成為全球最受歡迎的搜索引擎(Search Engine),大大超越了老牌入門級的搜索引擎網站Yahoo!,成為大多數網民的首選。以Google為代表的新一代搜索引擎不僅僅只依靠META標簽和網頁內容的相關度來排名,而是被其他網站錄接的數量作為一項重要的排名指標,Google排名規則不僅關注網站設計本身,而且還受其他因素的限制。Google的演算方法一直是個秘密,并且時刻在改變著,據說影響Google排名的因素有三百多種。事實上,Google搜索引擎采用了全新的搜索方式,通過一種復雜的數學分析,估計出一次搜索查詢后反饋的網頁的質量或重要性及相關主題。要知道一個網頁的質量,Google可以通過有多少網頁與它連接來判斷,這是因為人們不會與糟糕的網頁做鏈接。傳統的搜索引擎如Hotbot和Lycos等當前使用的是元素搜索技術,即使用網頁中的的關鍵字進行搜索,而Google則使用一種包含對整個網絡的連接結構進行分析和大規模資料挖掘的技術,Google不僅掃描搜索關鍵字,還閱讀頁面全文,考慮到圖像和所有鏈結,然后把該頁面與類似頁面劃分開來。

    因此,Google排名靠的是經驗、資源、細節方面的技巧。在網絡行銷界,有句很有名的話,那就是"網絡行銷,細節制勝"。Google排名同樣是這樣的道理。

    如果你的網站想在Google排名搜索結果排到前面,首先,你要把自己的網站建設做好,然后按情況進行改革。如果你沒有時間和精力去做這些工作,可以找相關的服務公司或者個人工作室來做。不過,不要因為自己不了解而花掉冤枉錢。比如網絡行銷公司常常讓客戶購買一些并不常用的關鍵字或所謂的熱門關鍵字,或者要求客戶支付過高的價格等等。

    3.搜索引擎行銷的目標層次和網站優化設計

    搜索引擎行銷的基本思想是讓用戶發現資訊,并通過點擊進到網站/網頁進一步了解他所需要的資訊。在介紹搜索引擎策略時,一般認為,搜索引擎優化設計主要目標有2個層次:被搜索引擎收錄,在搜索結果中排名靠前。這已經是常識問題,多數網絡行銷人員和專業服務商對搜索引擎的目標設定也基本處于這個水平。但從實際情況來看,僅僅做到被搜索引擎收錄并且在搜索結果中排名靠前還不夠,因為取得這樣的效果實際上并不一定能增加用戶的點擊率,更不能保證將訪問者轉化為顧客或者潛在顧客,因此只能說是搜索引擎行銷策略中兩個最基本的目標。

    利用搜索引擎工具可以實現4個層次的行銷目標:

    1)被搜索引擎收錄;

    2)在搜索結果中排名靠前;

    3)增加用戶的點擊(點進)率;

    4)將瀏覽者轉化為顧客。

    在這四個層次中,前三個可以理解為搜索引擎行銷的過程,而只有將瀏覽者轉化為顧客才是最終目的。在一般的搜索引擎優化中,通過設計網頁標題,META標簽中的內容等,通常可以實現前兩個初級目標(如果付費登錄,就直接可以實現這個目標了,甚至不需要考慮網站優化問題)。實現高層次的目標,還需要進一步對搜索引擎進行優化設計,或者說,從整體上設計對搜索引擎友好的網站。(參見本文"網站的持續改進"之"改進網站以盡量對搜索引擎友好"。)

    二.網絡廣告

    網絡廣告和與其他大型知名網站合作專題是許多大企業在網絡行銷上經常采用的手法,其優點在于影響面廣,宣傳效果好,同時有利于企業品牌的提升,缺點在于費用太高,需要專業的行銷策劃團隊配合,以及設計人員的協助等。該手段適合大型知名企業采用,而對一般中小型企業來說,較可行的方法是選擇本行業內較知名的網絡媒體合作,這樣一方面可節約宣傳成本,另一方面目標群體更為明確有效。此外,不定期的更換企業網站上廣告條(banner),有針對性對企業產品、品牌展開宣傳,也是一種行之有效的手段,在企業網站上也開設專題區,定期策劃宣傳專題,有針對性地進行宣傳,同樣可起到引導用戶,從而達到宣傳效果。專題的選擇可以是產品、活動、事件、互動調查等。

    競價排名是搜索引擎關鍵字廣告的一種形式。其中以Google公司推出的關鍵字廣告Adwords業務最為有效和常用。通過Google Adwords(http://www.google.com/intl/zh-CN/ads/)。

    你可以自行制作廣告,選擇關鍵字,廣告出現在所選擇的"關鍵字"的相關搜索頁面右側。收費原則是點擊付費(Cost Per Click),從而使得廣告非常具有針對性,最低每次點擊0.05美元的收費使得該業務尤其適合中小型企業開展網上宣傳。

    例如,在Google中鍵入"印刷"關鍵字,搜索所有中文網站,在其搜索結果右側的"贊助商鏈結"中將出現已經購買了印刷關鍵字的印刷企業的廣竹土口,目前共有8家,包括上海金粟印務有限公司、廣州皇信彩印紙品有限公司、深圳極雅致印刷有限公司、深圳新聯美術印刷廠等。

    至于企業如何直接在Google上投放廣告以節省費用,由于篇幅限制,在此不做詳細介紹,讀者可參見專題文章:《如何在GOOGLE上投放廣告》(http://www.linkwan.com/gb/articles/97.htm)。

    三.E-mail行銷與垃圾郵件

    目前,國內互聯網用戶使用最多的是電子郵件,這從另一方面也可以看出電子郵件行銷的重要性及其作用。不過,現階段電子郵件行銷的重要性及其作用。不過,現階段電子郵件行銷還不是十分規范,存在著不少問題,因此,筆者認為,如果企業有實力,不妨采用企業電子雜志與電子郵件行銷相結合的手段,效果將非常顯著。

    具體做法是,組織或成立專門的編輯部,負責企業各種資料的撰寫、收集和整理,定期把宣傳內容制作成電子雜志的形式掛在網站上,并設計訂閱,退訂視窗,如果用戶喜歡你提供的內容,就會主動訂閱。通過這種手段,企業可以收集到第一手客戶資料,為日后有效的電子郵件行銷打下良好基礎。不過,筆者建議,初期開展電子雜志可借助外界電子郵件行銷服務公司協助發送雜志,待形成規模后再主動傳播。電子雜志傳播方法如果得到有效實施,不但會給企業宣傳帶來極大提升,而且也有助企業網站訪問量提高。

    值得提出的是,以垃圾郵件方式行銷。企業應該對規范的電子郵件行銷方式有必要的了解。警惕有些打著網絡營銷旗號的"網絡營銷軟體"、"分類郵件地址"名義垃圾郵件發送者以"定向發布資訊"、"搜集潛在客戶"、"郵件群發是最好的網絡營銷手段"等口號混淆垃圾郵件與許可E-mail行銷的概念,使得一些企業和個人在對正規的E-mail行銷缺乏了解的情況下發送垃圾郵件,或者委托垃圾郵件發送者發送廣告資訊。

    四.其他網絡行銷方式

    1.網絡行銷與傳統行銷的相互配合

    廣播、電視、報紙、雜志等傳統媒體的行銷廣告是"廣播"方式,即這些廣告的觀眾不全都是你的目標客戶。與此相比,Internet網絡行銷的最美妙之處在于由于網絡搜尋資訊的特有方式,人們通過搜索引擎或其他網站的鏈結找到你的網站,獲取產品或服務資訊,決定了網上行銷的觀眾幾乎全都是你的目標客戶,及"窄播"效應。很顯然,只有對某種產品或服務感興趣的人才會鍵入與此產品、服務相關的關鍵字,從而找到此種產品或提供此種服務的商家。因此建議企業在形象設計(CI)中加入企業的網址,將企業網站作為企業形象(CI)的一個部分,在其他傳統媒體(電視、廣播、報刊、雜志等)的廣告中有意識地加入網址,兩者相互促進。

    此外,企業在日常的營銷工作中,也要有意識的加入網站宣傳工作。比如,在企業會議室、會客室、業務洽談室等地方醒目地打上自己的網址,并告訴客戶可以通過企業網站了解企業業務和獲得相關資料等。以及在企業的各種宣傳冊、廣告、信紙、傳真、名片、贈品上,印上企業網址和E-mail信箱。這樣,既能體現企業的品位,又能讓想了解企業的人可隨時隨地上網瀏覽網站。

    2.網絡會員制行銷

    網絡會員制行銷是電子商務中一種有效的行銷模式。目前網絡會員制行銷已經在國內大型網絡公司獲得了廣泛應用,不僅受到大型電子商務網站的重視,也擴展到其他網絡服務領域,如搜索引擎的競價排名、競價廣告等。尤其是在2003年上半年,以"短信聯盟"為代表的網絡會員制行銷模式風風火火,幾乎到了過熱狀態。

    其他的網絡行銷方式還有:鏈結交換、間接網頁策略(也叫迷你網站)、新聞組討論、電子公告欄(BBS)、結合行銷、CRM(客戶關系管理)網絡行銷等。

    五.網站的持續改進

    1.網站診斷

    通過網站訪問日志報告,分析網站中的那幾頁的被調閱率最高,了解訪問者對你的產品或服務中的那幾項最感興趣,并在這幾頁中增加更多內容和資訊,然后以此為主要內容向目標市場推介。

    網上行銷是一個實踐-認識-再實踐-再認識的過程。你需要根據訪問流量和實際的銷售業績比較,看看影響成交率的是哪些因素,來制定出銷售重點和銷售策略,再根據實際的市場反應來修正你的銷售策略和重點,以及確定哪些網上行銷方法最有效,然后再主動出擊,有的放矢地進行網上行銷。

    筆者要重申網站更新的重要性,其原因有三:

    1)搜索引擎傾向于將經常更新的網站在搜索結果中排位靠前;

    2)網上行銷需要你經常更新網站的內容;

    3)經常更新網站會增加公司的信任度。當看到很多網站的最近更新日期是幾個月或一年前,筆者就會發出這樣的疑問:燈總是亮著,但有人在家嗎?

    為此,建議至少每個月更新一次網站,哪怕只是做最細微的改動。

    2.改進網站以盡量對搜索引擎友好

    有些企業網站非常重視網頁的視覺效果,尤其是首頁,常常使用很復雜的圖片,或者用Flash等Rich Media形式來展示企業形象,這些固然能從視覺上引起人們的注意,但從搜索引擎優化的角度來看,沒有任何價值,甚至起到反作用,讓搜索引擎無從檢索,用戶也就無法通過搜索引擎發現這個網站。

    因此,應該在兼顧實用的前提下追求美觀,而不是將美觀放在首位,在兩者之間必須權衡取舍時,寧可放棄外在的美觀,因為對于對視覺效果并沒有完全一致的評價標準,但搜索引擎卻有共同的檢索基礎,對搜索引擎不夠友好,失去的將是自己的潛在用戶。強調網站的實用還有一個重要原因:用戶通過搜索引擎來到一個網站,他們不是為了欣賞網頁的視覺效果,而是為了獲得與他在搜索引擎中所使用的關鍵字相關的資訊。可以想象,如果用戶進入一個網站卻沒有發現自己需要的資訊,他唯一的選擇就是盡快離開,這大概不是網站經營者所期望的結果吧!

    網站設計對搜索引擎不友好,表現在多個方面,最糟糕的是使得搜索引擎無法檢索資訊,或者得到的檢索資訊讓用戶看起來沒有吸引力。造成網站對搜索引擎不友好的主要原因是:

    大量采用圖片形式,沒有可以檢索的文本資訊;

    網頁沒有標題,或者標題中潒有包含有效的關鍵字;

    網頁正文中有效關鍵字比較少;

    網站導航系統讓搜索引擎"看不懂";

    部分資料庫資訊對搜索引擎"保密";

    沒有與其他網站提供鏈接線索進行比較。

    另外,除了考慮網站的設計、流量的增加、排名提升外,一個非常重要的問題是維持網站的穩定運行和擁有較高的訪問速度。試想,一個排名非常靠前的網站,因為伺服器出現問題而造成無法訪問,后果會如何?所以,如何降低伺服器故障及優化伺服器功能一直是業界所關心的話題。訪問速度和穩定性乃優秀網站之重要指標,亦是提升網站瀏覽率的物質保障,在伺服器世界里,"穩定代表一切"。


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(153) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229638  發表時間: 2008年06月19日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    訪問速度和穩定性乃優秀網站之重要技術指標,亦是提升網站瀏覽率之重要環節。在伺服器世界里,穩定代表一切。按業界的一般標準,高檔伺服器產品的穩定度達99.99%,也就是說伺服器運行一年內的當機(Hang)時間平均不超過53分鐘,中檔伺服器的穩定度為99%,平均當機時間是88小時,低檔伺服器的穩定度僅為90%,平均當機時間高達876小時。

    數據中心伺服器托管一般都是采用1U、2U機箱,尤其是訪問量大的mail、web、ftp類的伺服器,對穩定度的要求很嚴格。如何降低伺服器故 障及優化其性能一直是業界所關心的話題。要達到百分之百的零當機是不可能的,我們要做的是深入分析影響伺服器穩定度的關鍵問題,采用針對性技術有效提高伺服器的穩定性,使當機時間盡可能地縮短。

    就筆者的實際經驗而言,影響伺服器穩定與安全之因素主要有伺服器的電源供應器、散熱系統、伺服器主板選擇、軟件運用等。本文將就上述硬件的合理配置、如何評測、以及伺服器軟件設置、優化等方面的問題進行探討。

    一、電源供應器

    熟悉電腦的用戶都知道,電源質量的優劣直接影響到系統的穩定和硬件的使用壽命,并不僅僅是將220V市電的交流電轉變為電腦所需要的低電壓強電流的直流電這么簡單。

    如果將CPU(處理器)比擬做一臺伺服器的大腦,那么電源就可以說是伺服器的血液了。伺服器對電源的要求不僅是要求提供穩定的電流和較高的功率,還必須能應付各種苛刻的工作環境,同時還要求常年不間斷地工作。隨著CPU主頻的提高,功耗將越來越大,硬盤(Harddis)容量和轉速等也越來越大、越快,這對電源的要求就更高了。伺服器通常支持的CPU可以達到2個甚至更多。所使用SCSI硬盤約為2-4個,RAM容量2GB以上,以上配件在消耗能量方面都是驚人的。比如Intel P43.2G CPU 功耗達到82W(瓦特);Prescott 0.09微米制程P4-E 3.2G更達103W,所以目前Prescott CPU 己不適合應用在1U、2U機箱做伺服器。而SCSI硬盤的功率也在10W以上,所以伺服器系統所需要的功率遠遠高于一般PC,一般PC只要200W電源就夠用了,而伺服器1U機箱應有300W,2U應有350W。

    高品質電源是伺服器正常運行的重要保證,也是一般人最容易忽略的。實踐經驗告訴我們,電源導致伺服器經常自動重啟(Reboot),致使硬盤出現壞道。功率不足使+5V、+3.3V和+12V在滿負荷狀態運行時(CPU使用率保持在100%,硬盤也在大量讀寫資料,功率消耗大)出現電壓波動,或者散熱不良造成過熱,是經常性自動重啟的主要原因,造成伺服器不能正常提供服務,同時也會縮短硬件的壽命。

    二、散熱

    散熱是伺服器要解決的首要問題之一。伺服器硬件一般放在1U、2U機箱內配合機架統一使用,機架伺服器的寬度為19英寸,高度以U為單位(1U=1.75英寸=44.45毫米),在狹小的空間內有大量的硬件高速運行狀態下散發的熱量非常大,且伺服器一般要求24小時不間斷工作,如果機箱材料的選用或內部結構設計不良,導致整體散熱性能差,則會經常導致伺服器出現當機、重啟等狀況。

    首先,伺服器機箱的選料就馬虎不得。首選全鋁質的或者鋁合金的,次選鐵板。顏色應漆成黑色,以利于散熱。采用全銅及直接整體銅切割出來的CPU散熱器較好,其散熱效果優于其它材料,是伺服器CPU散熱的理想選擇。但為達到最佳散熱效果,須配合品質良好的散熱膏并正確地使用。筆者采用Arctic Silver 5純銀散熱膏,嚴格按照說明書操作,成功將CPU溫度降低3-4℃。

    再者,采用高風量(CFM)散熱風扇對伺服器來說也是關鍵組件,散熱風扇一般分滾珠軸承、油封軸承兩種。滾珠軸承較為耐用,所以廣泛應用,雖噪聲略高,但實際上伺服器放在機房中,噪音干擾不成問題。判斷風量的大小可以從風扇注明的A(電流量)或W(功率)來作選擇,數字越大風量越強。可選擇Delta、Sunon、Nidec、Sany、Y.S.Tech等名牌,以確保長期運轉不出故障。為提高散熱效果,也可選用小型鼓風機(BLOWER)。筆者使用的伺服器,選用小型鼓風機配合1U機箱,另加6個萬轉4CM電流0.24A強力風扇使機箱溫度降低了8-10℃左右。有興趣了解各類強力風扇的朋友可到超頻專門店網址http://www.pcbulb.com/查詢。近期Sany推出1.5萬轉4CM電流0.55A風量20.83CFM超強力風扇是1U伺服器散熱較佳配搭。

    另一方面要合理設計風道,在安裝好硬件后把機箱內的cable、電線整齊地扎好,以保證機箱內氣流循環無阻,能更有效地對CPU、RAM、硬盤、南北橋晶片等進行散熱。Intel P4CPU溫度75℃、AMD CPU溫度86℃是工作溫度極限,高溫時CPU將會自動降低工作效率。所以在1U機箱伺服器P4平臺full loading CPU溫度能維持65℃左右及機箱溫度50℃以內可算不錯的散熱效果。注:(Intel 的設計規范CPU溫度不超過72℃)

    三、主板

    不可置疑,主板對于伺服器至關重要。主板猶如人的骨架,承載著CPU、RAM(記憶體)等重要部件的運行。如果你的伺服器電源質量可靠,功率充足;機箱及CPU散熱良好,但仍偶爾會莫名其妙的當機,就該考慮問題可能出自主板了。有些主板在當機后,因有自我保護功能,必須關掉電源再開機;更有甚者,必須清除CMOS中的記憶,才可以重啟,這對伺服器的遠程維護與管理造成嚴重障礙。

    INTEL主板是少數通過WHQL微軟WINDOWS操作系統硬件質量認證的產品,穩定性和兼容性經受實際考驗,INTEL生產的主板嚴格遵照規格制造。在性能方面INTEL原廠伺服器主板針對WINDOWS操作系統做了優化設計,加上INTEL對自己生產的處理器最為了解,更容易釋放出自家處理器的性能,可以說INTEL的主板是高品質與高性能兼具的產品。但是INTEL也有為了穩定性而犧牲性能的傳統,與同級的主板晶片組比較,INTEL的主板總是比其它大廠的主板要慢上一點,功能方面也沒有太多的擴展性。但是在伺服器最注重穩定性的原則上,筆者強烈推薦采用INTEL主板。

    四、評測

    綜上所述,電源、主板及散熱是如此重要。直接影響到伺服器的穩定與安全,那么,你要如何判斷其好壞呢?下面,我們將自己動手進行評測,去了解自己的伺服器是否處于一個良好的工作狀態。

    測試平臺的搭建,主要考慮電源輸出電壓的穩定和主板、CPU等機箱內關鍵部分溫度的測試。對于電源的測試相對比較簡單,我們當然沒有必要像專業電源制造廠商一樣,用示波器、萬用表甚至用ATE(自動測試儀)等專業工具來進行測試,僅通過軟件來進行測試就足夠了。雖然通過軟件測試只能作為一個參考,所測值可能會與你的電源的真實值有所差距,但是通過這個測試,我們還是能大概看清自己伺服器中電源的"真實面目"。當然,探測主板及CPU的溫度,用軟件來測試也是很容易的事了。

    Windows任務管理器可以監視電腦的CPU 和RAM使用情況、程式和進程的相關信息。建議搭配下述推薦評測軟件共同使用。

    *MBM5溫度、電壓監控軟件

    MBM5是一款用來探測主板CPU溫度以及電壓的軟件。推薦使用Motherboard Monitor 5(以下簡稱MBM5)來測試。MBM5最新5.3.6.0英文版本、最新5.3.6.0多語言版本。其適合作業系統:Windows 9X/Me/2000/XP,可在世界網絡:http://www.linkwan.com/gb/download/下載。

    當溫度超高過你的設定值時,MBM5便會啟動警示音樂或是顯示警示文字,還可以輸出TXT或HTML格式的日志文件。

    安裝MBM5完成后,開始設置,這是關健的一步。因為不同主板的檢測晶片是不同的,所以要先設定了MBM5。在程式集里面找出MBM5,然后運行MBM 5Config Wizard。

    如下畫面出現,點擊NEXT。

    如安裝好的MBM5不能完全支持你最新的主板,請試試點擊Update(升級),一般更新后軟件會對更多新主板支持。升級完成后,進入下一步,出現如下畫面,列出許多廠家和主板型號,根據你的主板,選擇相應的主板廠商和主板名稱。比如,筆者的主板為Intel S875WP1-E,選好后點擊NEXT。

    之后會出現一些選項,比如選擇溫度單位是攝氏度(Celsius)還是華氏度(Fahrenheit)。不同的主板也可能會出現不相同的設定,一般使用默認。

    最后點擊Finish。到了這一步許多朋友可能會想,這樣就應該完成MBM5的安裝了吧?其實不然。還有一個非常重要的設置,否則,MBM5測出來的值是不正確的。

    運行MBM5,打開管理界面,在安裝了語言包后,你可以選擇繁體/簡體中文。

    然后在Voltages(電壓)中,Voltages Configuration(電壓適配器)要選擇自己的主板的型號,如果在列表中沒有你的主板型號,請先不要急,那是因為一般的主板都是采用標準的ITE8712F傳感器,但你也可以對應你的主板進行相應的選擇。

    顯示CPU溫度、主頻,風扇轉速、機箱溫度

    點擊Apply(應用)后,再看一下Dashboard看看是否都正常。該軟件具體的使用,大家可按提示操作。

    *OCCT電源測試軟件

    談到電源質量的測試,就不得不提一下OCCT這個軟件。其適合作業系統:Windows 9X/Me/2000/XP 可在http://www.linkwan.com/gb/download/下載。

    OCCT需要和MBM5這個軟件共同協作才能為用戶提供一份完美的電源質量報告。在測試過程中,OCCT通過MBM5所測出的資料,自動模擬電腦滿負載的狀態,讓電腦連續30分鐘滿負載運行,最后得出相應的電壓波動圖表,通過這些圖表,用戶就可以判斷出電源是否令人滿意了。

    在安裝好MBM5及OCCT后,點擊桌面捷徑方式就可以進入OCCT的主界面了。首先點擊右下方的"Option"(選項)鍵進入設置界面,在這里用戶可以對測試電壓的負載進行設置,供用戶選擇的有"Lowest"(最低)或者"Highest"(最高)等5個等級,還可以設置使用內存(RAM)的大小、CPU溫度以及輸出圖像的格式。設置完畢后,點擊"Go Back"(返回)回到主界面,再點擊左下方的"Test"(測試)鍵就可以對電源進行測試了。

    測試將進行30分鐘,這期間,OCCT占用系統資源很多,用戶最好不要進行其它操作,否則可能會出現死機。測試完畢后,OCCT將把測試結果以分析圖的方式呈現在用戶眼前,這些分別是"系統(機箱)溫度變化"、"CPU溫度變化"、"+5V的電壓波動"、"+3.3V的電壓波動"、"+12V的電壓波動"以及"CPU電壓波動"。

    如果用戶的電源品質良好,那么圖表上的各種電壓波動幅度會非常小,即使有波動也是在正常范圍之內;如果用戶電源質量比較低劣,那么圖表上各種電壓的波動范圍也會相應較大。

    OCCT還可以單獨對CPU進行測試,只要點擊主界面下中間的"Torture"(CPU穩定檢測)鍵就可以對CPU進行穩定性測試,并向用戶報告錯誤。另外,由于OCCT可以實時監控CPU溫度、系統(機箱)溫度以及電源各個輸出電壓的情況,所以它也可以作為一款監控軟件使用。

    好了,我們終于可以開始我們的測試了。打開OCCT軟件(它會自動關掉MBM5)點擊test(測試)。你可以去休息了,約半個小時后再來看看成績吧。

    在OCCT進行測試的過程中,它會模擬你的伺服器在滿負荷的狀態下運行。在這期間,我們來了解一下伺服器的電源吧。為了保證電源的輸出穩定,伺服器電源供應器都設計了一套自動補償電路,也就是當電源的其中一組電壓需要更大的功率的時候,它就會提高那組電壓的輸出電壓,但由于不是每組電壓都可以單獨進行補償,也就是說,我們的電源在提高一組電壓的同時,其它的所有電壓均會相應的提高。這樣,就會形成一個特殊的現象,比如+5V因為負載太大而導致輸出電壓開始下降,電源會同時增加所有的輸出電壓,并不會單獨對+5V進行控制,其結果必然導致其它電壓組因為輸出電壓過渡補償而超過額定的電壓,當電源設計欠佳或輸出功率不足時這種特有的現象就更加明顯!這樣,電腦內許多設備都會在較高的電壓環境下工作。

    那什么范圍才算是合理波動呢?電源輸出的正電壓,合理的波動范圍在-5%~+5%之內,而負電壓的合理波動范圍在-10%~+10%。

    只要電源的輸出在合理的范圍內,對電腦的配件都不會造成負面影響的,所以也不用過分地關注波動的大小。但波動的相對大小,側面反映了電源的負載能力,波動率相對越小的電源,其實際的最大輸出功率可能越大。

    下面我們來看看測試結果吧,筆者的測試是在以下平臺完成的:

    CPU :P4 2.8G (800FSB)

    RAM :1G DDR400RAM

    主板:Intel S875WP1-E

    硬盤:WD360DG,36G 1萬轉SATA

    電源:美基350CD(300W)

    首先來看看CPU溫度,從圖中可以看出,從44℃升到64℃。看起來還是不錯的。

    +3.3V電壓,大致波動范圍是3.3195-3.336V,還不錯,是在正常范圍(3.14-3.46V)內,此電壓主要應用在顯卡、PCI、南北橋等設備。

    再來看一下,系統要求最高的+5V電壓,看這個圖,波動曲線還不算大,在(5.123-5.16V)范圍內供電包括CPU(舊式主版)、RAM、硬盤、光驅、I/O及主板的其它設備。

    +12V,波動范圍在11.85-11.975V,波動范圍看似挺大的。主要應用在耗電量比較大的設備上,例如風扇,硬盤、光驅,新式主版用來轉換為CPU所需的電壓。

    CPU電壓,我在BIOS中設置的是1.45V,所以測試出來的結果也是在1.45V左右,看起來還是平穩。

    測試結果看完了,該電源供應器總的來說非常不錯,雖然所有電壓均稍微偏離中心值,但均在安全的范圍內。OCCT不對負電壓進行測試,因為這幾個電壓的輸出電流均小,而且相應的正電壓的值也就可以大概看出負電壓的波動。除了看波動范圍,還需看波動大小。由下表可見筆者伺服器所用美基350CD電源的電壓波動幅度非常小。

    電壓 合理波動范圍 美基350CD (300W)實際波動范圍 穩壓精度
    +5V 4.75-5.25V 5.123-5.16V 3.04%
    +3.3V 3.14-3.46V 3.3195-3.336V 1.1%
    +12V 11.4-12.6V 11.85-11.975V 1.07%

    *Hot CPU Tester系統穩定度測試軟件

    為進一步考驗伺服器的穩定性,筆者還給大家介紹一個不錯的軟件-Hot CPU Tester。其作用是考驗CPU的穩定性以及散熱系統的優劣(需要溫度監控軟件配合使用),不過在烤機(燒機)的時候還有一個附加功能,那就是可以發現CPU是否被超頻。其最新版本:4.0,其適合作業系統:Windows 9X/Me/2000/XP,可在http://www.linkwan.com/gb/download/下載。

    安裝好Hot CPU Tester,桌面會顯示一個icon ,雙擊icon進入Hot CPU Tester的主界面。下面主圖左邊是菜單,在這里我們可以看到7個選項,分別是"Diagnotisc"(檢測運算測試)、"Burn-in"(CPU、RAM測試)、"Benchmark"(基準測試)、"System Info"(系統信息)、"Option"(選項)、"LiveSupport"(在線支持)以及"About"(關于)。可以看出,Hot CPU Tester是一個非常全面的測試軟件,在這里,我們著重介紹幾個Hot CPU Tester的主要功能。

    *穩定性測試

    穩定性測試主要是依靠"Diagnotisc"(檢測運算測試)和"Burn-in"(CPU、RAM測試)兩個功能。只要在"Diagnotisc"(檢測運算測試)的界面中單擊"Run Test"(開始測試)鍵就可以開始對系統進行測試。這個測試是讓伺服器連續運算各種項目,使CPU在一段時間內保持使用率為100%,以此來測試CPU的穩定性。

    中間的界面是測試的項目,包括硬盤、內存(RAM)以及MMX等,下方有CPU資源占用的情況,通常不到幾分鐘,CPU使用率就會達到100%。如果在這種狀態下能讓Hot CPU Tester運行達1小時以上,那么CPU的穩定性就算達到標準了。另外,由于CPU長期在100%狀態下工作,會產生極大的熱量,這個時候通過MBM5溫度測試軟件就可以看到CPU及系統的溫度,并以此判斷散熱系統的優劣了。

    在右下方,Hot CPU Tester會顯示測試進行的時間,以及開始測試和結束測試的時間。另外,在Option(選項)中還可以對測試進行一些設置,比如測試的時間以及測試時硬件的狀態,有一些功能需要用戶注冊后才能使用。

    如果你只想測試CPU和內存,那么可以進入"Burn-in(CPU、內存測試)"的界面,在這個界面中可以設定測試的次數以及測試內存的大小,然后直接點擊"Run CPU Burn-in(開始測試CPU)"鍵或者"Run Memory Burn-in(開始測試內存)"鍵進行測試。

     

    小提示:在進行測試的時候,由于伺服器CPU的資源占用率達到了100%,所以這個時候操作其它程式都是危險的,極可能引起系統崩潰,所以在進行Hot CPU Tester測試的時候,應該關閉其它程式。

    *性能測試

    在Hot CPU Tester中也有類似PCMark2003的系統性能測試。進入Benchmark(性能測試)菜單中,點擊右上角的"Run Benchmark"(開始性能測試)就可以對系統整體性能進行測試,測試項目在中間窗口中顯示,測試結果會出現在"Total Score"(總分)的空格中。

    五、伺服器軟件優化

    提到系統優化,我們有必要區別碎片整理和系統優化的概念。前者指系統向磁盤存儲的文件體積大于磁盤提供的連續存儲空間時,因此不得不將文件拆開分別存于幾塊不連續的物理磁盤區域,從而產生了所謂的磁盤碎片,而通過軟件的調整將其轉化成連續區域的過程稱為碎片整理。系統磁盤優化則全然不同,它有兩個方面:首先,根據文件調用的頻繁程度來調整它們在磁盤中的位置,把使用頻繁的文件放在磁盤開頭以達到最短的調用時間;另外一個過程恰好與碎片整理相反,就是整理未被占用的磁盤空間,讓它們連成一片,使以后磁盤碎片產生的可能性降至最低。

    對訪問量大的伺服器,定期的磁盤整理對于提高硬盤訪問效率、保持系統穩定性非常有用。一般用戶都是習慣使用WINDOWS自帶的磁盤整理工具,它的優點在于工作時只占用CPU 10-30%適合伺服器在線時整理,不影響服務但其速度和效能往往不能令人滿意。

    現介紹二個優秀磁盤優化軟件:

    1)Norton Utilities

    Norton Utilities是諾頓工具包Norton SystemWorks 2003中的一個組件,該軟件是一個功能強大的磁盤修復、磁盤優化、系統維護和系統優化工具。在你的伺服器上運行該軟件后,你將會發現Norton Utilities所具有的那些性能強大的功能是不可缺少。系統優化(Optimize Performance)選項中的Speed Disk工具,可用于優化系統磁盤,將最常用的檔案放在硬碟最前端,使存取時間更短,以提高伺服器性能。優化磁盤的步驟非常簡單,大家按下Optimization Map,在右邊選擇一個需要進行優化的磁盤分區,再按Start Optimizing即可開始優化磁盤。

    在優化過程時,我們可以發現,Speed Disk的整理速度要比Windows自帶的碎片整理程序快許多。但由于工作時占CPU使用率就會達到50%左右,如伺服器在線時流量大,可能會影響服務。筆者在一臺使用Intel P42.8GHz處理器、1G內存、安裝WINDOWS 2000SERVER的伺服器上對Norton Utilities進行了測試。為了測試該軟件,我們在開啟許多應用程式的情況下反復的重啟伺服器、向注冊表中添加許多錯誤條目、將程式的捷徑指向錯誤的可執行檔案,并且在電腦中反復安裝和解除安裝軟件以便能夠在硬盤中產生大量磁盤碎片。在我們所做的測試中,Norton Utilities成功地報告各項錯誤,而且很好地完成了修復工作。查找及修復系統問題上Norton System Doctor(系統醫生),監測的內容要豐富得多。還有Norton Disk Doctor(磁盤醫生)和Norton System Check(系統檢查)等,功能都很強大。

    2.Voptxp V7.12

    除了Norton Utilities外,Voptxp v7.12也是優秀磁盤軟件,可以把磁盤一些詳細資料顯示出來包括:磁盤使用和剩余空間圖例結構圖,當前磁盤碎片個數情況,當前磁盤文件和文件夾個數,分區大小,不連續文件個數,交換文件的情況等,和傳統的磁盤碎片整理程序比較,Voptxp v7.12有著更大的優勢:多任務窗口、速度快、功能強大等特點,更在"優化"選項中有:互聯網優化和系統優化兩個不錯的功能,是一個完美的測試工具,幫你節省更多時間。

    除系統及硬盤的維護問題外,操作系統的安裝與配置、系統的及時更新與升級、殺毒軟件的使用及日常的管理和維護等都是非常重要的。筆者就自己日常管理網站伺服器的經驗,整理出來供大家分享。

    a、定期查看系統/網站日志,查看是否有異常報錯,以便找出網站存在的問題。系統有那些缺陷,可通過系統日志反映出來,通過網站日志,可以找到那些頁面有錯誤、那些頁面需優化、那些圖片及文件應刪除或減肥使網站訪問的效率提升。查看網站日志最好是能安裝相關的網站日志分析工具,使日志更直觀。

    b、必要時重啟伺服器也是提高訪問速度的方法之一,WIN系統定期重啟是必要的,以釋放一些使用完而沒有被釋放的資源。

    c、當使用ACCESS數據庫時,數據庫最好是分多個文件來處理,這樣讀取和存貯速度都會快很多。數據庫很大時最好是用MS SQL,不論是處理資料還是 數據容錯性都會有一個質的提升,使用MS SQL要定期對SQL數據庫日志進行清理,清理SQL的日志有利于降低系統資源的使用,特別是內存的占用率。

    d、經常留意伺服器的資源使用量,查看是那些程式占用的系統資源比較高,是那些程式或那些內容引起的,是否屬于正常。留意系統最新的(Service Pack)補丁程式和病毒,及時更新相關軟件,打補丁程式要先在其它機上測試后再在伺服器上安裝,以免引起兼容性的問題。查看伺服器的流量,隨時分析伺服器狀態,通過流量可知伺服器是否正常,如有駭客或入侵都會產生比較大的流量。

    e、WIN2000在默認情況下會安裝一些常用的組件,但是這個默認安裝是極度危險的。你應該明確地知道你需要那些服務,而且僅僅安裝你確實需要的服務。根據安全原則,最少的服務+最小的權限=最大的安全。典型的WEB伺服器需要的最小組件選擇是:只安裝IIS的Com Files,IIS Snap-In,WWW Server組件。如果你確實需要安裝其它組件,特別是:Indexing Service,FrontPage 2000Server Extensions,Internet Service Manager (HTML)這幾個危險服務,請慎重處理。其它的不在此詳述。

    經過評測,您是否擁有了一臺性能穩定、處于良好工作狀態的伺服器,為迎接隨后接踵而來的訪客做好準備了呢?是的,經過了前期細致的建站準備工作,又經過了緊鑼密鼓的網站規劃建設和網絡營銷工作,相信您網站的瀏覽率和知名度將會節節攀升,名列前茅。下期筆者將就優秀中文印刷網站的排名情況和本系列文章做最后的總結。希望不久的將來您能榜上有名


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(111) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229636  發表時間: 2008年06月19日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    目前國內用的最多的無非就是 美國-韓國-香港-臺灣-加拿大 日本 英國 德國 比較少吧!日本可能SEX的比較多!   今天做的比較,是自己有初步接觸,部分機房有用的,拿出來比較下:   1、比-速度   美國:(機房名地理位置-加洲、華盛頓、紐約、路易斯安娜、亞拉巴馬、北卡羅來那、德洲、喬治亞)   美國整體速度其實不錯,主要是看地理位置和機房!有些朋友都認為中國訪問美國的,不行,慢!其實未必,選擇一個好的機房,國內整體來說速度還是不錯的。 現在由于做SEX和六合的多,很多國內同行 都把客戶放到美國,一臺服務器上放了很多六合和SEX的用戶,沒有很好的控制,會造成訪問很慢,整體來說 美國的速度還是滿優秀的!   香港:(機房名地理位置-HKNET、新世界電訊、、ENET、城市電訊、和記、太平洋電訊)   香港原本連接國內速度其實很快的,真的可以說和國內一樣的快。可是大家都知道香港做六合的多,特別到了開獎的時候特別卡,有些客戶經常會罵 “你們香港服務器怎么那么卡啊?” 中國這么多人去訪問香港 能不卡嗎???   HKNET ENET盈科 新世界都是比較常用的機房,這幾個機房每個禮拜那幾天總是比較慢的!   新世界我用了1年多了,個人感覺還算滿意,但是最近比較不理想很糟糕!特別福建泉洲-廣東一帶的客戶訪問很不理想! 城市電訊 國內電信客戶訪問比較理想,可是和廈門電信一樣 快成為“稀有品種”了。 和機、太平洋都比較貴,適合大企業客戶!   韓國:(機房名地理位置-釜山、漢城、安山、大田、仁川、光洲、大邱、慶洲)   速度很明顯可以感覺的到!真的很不錯,可是由于價格的原因,能用的上的朋友,也不是很多。 記得落伍以前那個MR.L提供的韓國虛擬主機,速度大家都可以看的到的吧。   臺灣:(機房名地理位置-高雄 臺北 新竹 嘉義 苗栗 臺東 花蓮)   速度不錯,起碼我是在廈門,訪問的時候 感覺很不錯!但是好象很少人用,而且價格方面,也是有點不敢恭維,等會下面比價格的時候再詳細比。   臺灣在虛擬主機上控制的也不錯,他們SEX也特別的多,和美國一樣流量限制很嚴格,很少有商家做不限制流量的,做不限制流量的價格也非常的可怕!下面再提!   加拿大:(機房名地理位置-無)   加拿大,個人租用過一次,速度實在不敢恭維,不知道其他朋友用的怎么樣。   2、比-價格   美國-c42.4 512 80g MD機房算不錯 速度還滿理想的,價格約為 600-700元RMB 國際代購價算在內 國內市場價650-900元!   香港-c42.4 512 80g 新世界不錯,價格合理,速度現在不是很理想,市場價約為700-900,國內市場價900-1500元!   臺灣-c42.4 512 80g 臺中的還成,其他的沒用過,市場價在1000左右,國內做的價大概在1500以上,利潤滿高的!   韓國-c42.4 512 80g 市場價1000-1200左右 國內市場價1500-1900左右!   加拿大-不熟,不太了解!   3、部分商家推薦   http://www.smartinfo.com.hk/ 香港   http://www.asiahost.com.hk/ 香港的 性價比不錯   http://host.cigi.com.tw 臺灣   Ipowerweb.com   Globat   Startlogic   MidPhase   Powweb 美國的 性價比 不錯!   總結:   對于國內的朋友來說,美國-香港都是不錯的選擇!   美國100M asp+ac+asp.net(50IIS-100IIS) /php+MYSQL+5-10G月流量 市場價300-600 再貴 利潤實在太高了!   香港價格和美國差不錯!韓國臺灣的價格會比較貴點!   站點經營內容選擇:   企業用戶/個人用戶   此類用戶建議采用香港,臺灣的服務器或是虛擬主機。為什么不推薦使用美國? 因為美國畢竟有時差,如果是服務器在美國,日常的維護會比較麻煩,而且還有就是溝通上還是有差別,當然英語好的,那就不一樣了。   特殊用戶:   如XX,LHC,ZQ之類的客戶,此類客戶是非常的多,最常用的是 香港,但是香港IP少,而且封的也快。美國也是很不錯的選擇,美國有的機房速度也很快,但是好的機房價格又要比普通機房的價格貴1-1。5倍。但是美國優勢在于IP多,(下面會再舉例選購的誤區! ) 臺灣,臺灣其實也滿快的,但是價格和流量 是一個很大的屏障!   推薦 香港新世界/城市電信 (注意選擇IP段) 美國!   選購誤區:   1、現在市場上美國服務器都標 10個IP,注意,大家購買的時候要問清楚,是如何分配法。   美國機房現在開始抓IP,經常看到的IP分配為1+9 4+6 等。   注意,并不是網站上標明10個IP,就是一次性給你10條,而是第1次 可能給你1條,之后9條需要申請,但是申請了未必就是給你9條,有可能2條,3條這樣。 目前比較明顯的就是 美國的MD機房。   2、香港獨享帶寬   香港目前有2家以上提供每臺服務器獨享2M帶寬。 這里的2M是每秒2M,并且,根據不同商家,限制是不同的。   有的商家是限制2M,超過了就不行,有的說是2M,但是實際用起來有的超過4M。(我有個客戶就是做代理服務器的,之前和我合作的是一家香港公司,他們之前柜子機子少,所以當時客戶能跑到4M左右,沒做限制。)基本上2M獨享 大多商家還是有限制的!!! 但是,不要拿國內的10M和香港的2M對比, 可以說,香港城市的2M獨享 效果要比國內10M效果來的好,國內10M保證那些都是文字游戲,BS。 而且香港城市電信提供的帶寬,國內無論電信,網通,鐵通 訪問都特別的快。(這里拿出個自用服務器給大家測試203.186.128.225 ,)注意,同個機房不同的路由,不同的帶寬接入 還是有差別!!!
    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(77) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229634  發表時間: 2008年06月23日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

     

    其于window系統的同步實戰

    1. 遠程數據同步工具Rsync介紹

    1.1 軟件簡介

     

    Rsync是一個遠程數據同步工具,可通過LAN/WAN快速同步多臺主機間的文件。Rsync本來是用以取代rcp的一個工具,它當前由 rsync.samba.org維護。Rsync使用所謂的“Rsync演算法”來使本地和遠程兩個主機之間的文件達到同步,這個算法只傳送兩個文件的不同部分,而不是每次都整份傳送,因此速度相當快。運行Rsync server的機器也叫backup server,一個Rsync server可同時備份多個client的數據;也可以多個Rsync server備份一個client的數據。

     

      Rsync可以搭配rshssh甚至使用daemon模式。Rsync server會打開一個873的服務通道(port),等待對方Rsync連接。連接時,Rsync server會檢查口令是否相符,若通過口令查核,則可以開始進行文件傳輸。第一次連通完成時,會把整份文件傳輸一次,下一次就只傳送二個文件之間不同的部份。

     

      Rsync支持大多數的類Unix系統,無論是LinuxSolaris還是BSD上都經過了良好的測試。此外,它在windows平臺下也有相應的版本,比較知名的有cwRsyncSync2NAS

     

      Rsync的基本特點如下:

     

      1.可以鏡像保存整個目錄樹和文件系統;

     

      2.可以很容易做到保持原來文件的權限、時間、軟硬鏈接等;

     

      3.無須特殊權限即可安裝;

     

      4.優化的流程,文件傳輸效率高;

     

      5.可以使用rcpssh等方式來傳輸文件,當然也可以通過直接的socket連接;

     

    6.支持匿名傳輸。

     

     

     

    1.2 核心算法

     

      假定在名為αβ的兩臺計算機之間同步相似的文件AB,其中α對文件A擁有訪問權,β對文件B擁有訪問權。并且假定主機αβ之間的網絡帶寬很小。那么rsync算法將通過下面的五個步驟來完成:

     

      1.β將文件B分割成一組不重疊的固定大小為S字節的數據塊。最后一塊可能會比S 小。

     

      2.β對每一個分割好的數據塊執行兩種校驗:一種是32位的滾動弱校驗,另一種是128位的MD4強校驗。

     

      3.β將這些校驗結果發給α

     

      4.α通過搜索文件A的所有大小為S的數據塊(偏移量可以任選,不一定非要是S的倍數),來尋找與文件B的某一塊有著相同的弱校驗碼和強校驗碼的數據塊。這項工作可以借助滾動校驗的特性很快完成。

     

      5.α發給β一串指令來生成文件Aβ上的備份。這里的每一條指令要么是對文件B經擁有某一個數據塊而不須重傳的證明,要么是一個數據塊,這個數據塊肯定是沒有與文件B的任何一個數據塊匹配上的。

     

     

     

    1.3 命令語法

     

     rsync的命令格式可以為以下六種:

     

      rsync [OPTION]... SRC DEST

     

      rsync [OPTION]... SRC [USER@]HOST:DEST

     

      rsync [OPTION]... [USER@]HOST:SRC DEST

     

      rsync [OPTION]... [USER@]HOST::SRC DEST

     

      rsync [OPTION]... SRC [USER@]HOST::DEST

     

      rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]

     

      對應于以上六種命令格式,rsync有六種不同的工作模式:

     

      1)拷貝本地文件。當SRCDES路徑信息都不包含有單個冒號":"分隔符時就啟動這種工作模式。

     

      2)使用一個遠程shell程序(rshssh)來實現將本地機器的內容拷貝到遠程機器。當DST路徑地址包含單個冒號":"分隔符時啟動該模式。

     

      3)使用一個遠程shell程序(rshssh)來實現將遠程機器的內容拷貝到本地機器。當SRC地址路徑包含單個冒號":"分隔符時啟動該模式。

     

      4)從遠程rsync服務器中拷貝文件到本地機。當SRC路徑信息包含"::"分隔符時啟動該模式。

     

      5)從本地機器拷貝文件到遠程rsync服務器中。當DST路徑信息包含"::"分隔符時啟動該模式。

     

      6)列遠程機的文件列表。這類似于rsync傳輸,不過只要在命令中省略掉本地機信息即可。

     

    主服務器

    IP 192.168.0.100

    F:/data/www

    備份服務器

    IP 192.168.0.101

    F:/data/www

    實戰:

    1http://rsync.samba.org/ 下載cwRsync客戶端(cwRsync)和服務器端(cwRsyncServer)。

     

    2、服務器端安裝:采用默認選項安裝。

    安裝后,服務默認為手動啟動模式,到“管理工具/服務管理”里,啟動“RsyncServer”服務,并修改“RsyncServer”為自動啟動模式。

     

    1http://rsync.samba.org/ 下載cwRsync客戶端(cwRsync)和服務器端(cwRsyncServer)。

     

    安裝的過程很簡單,也很順利,從 cwRsync 網站上下載的 server and client ,都安裝了一下,不過后來發現,其實是不需要安裝 client 的,只要 server 就可以了,server 包括了 client 的功能。安裝完 server 后,會在 service 中增加 Rsync ssh 服務。

     

    服務器端安裝:采用默認選項安裝。

     

    安裝后,服務默認為手動啟動模式,到“管理工具/服務管理”里,啟動“RsyncServer”服務,并修改“RsyncServer”為自動啟動模式

     

    2、配置主服務器

    配置了一下 rsyncd.conf

     

    use chroot = false

    strict modes = false

    hosts allow = *

    log file = rsyncd.log

    pid file = rsyncd.pid

     

    # Module definitions

    # Remember cygwin naming conventions : c:\work becomes /cygwin/c/work

    #

    [test]

    path = /cygdrive/c/work

    read only = false

    transfer logging = yes

     

    只是將 [test] 中的 path 改成了我本機的備份目錄

     

    [www]

    path = /cygdrive/F/data/www

    read only = false

    transfer logging = yes

     

    3、備分服務器數據同步

     

    因為只是最簡單的數據同步,所以就不使用 ssh 了,直接啟動 rsync 服務就可以了。然后按照 usage 上面教的。

     

    rsync -av /cygdrive/F/data/www 192.168.0.100::www

     

    完成了數據的同步工作,一切順利。順便說一下,/cygdrive/d 是安裝完 cwRsync ,會自動將系統上所有的盤 mount /cygdrive/x x 表示盤符,小寫的,并把安裝目錄 mount / 了。

    這樣我們實現了從主服務器到備分服務器的數據同步

     

    下一步我們結合windows的任務調度來實現這個批處理文件,取名為XXX.cmd

    rsync -avr --ignore-errors --force 192.168.0.100::www /cygdrive/F/data/wwwroot

    test.bat

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

    @echo off set path=%path%;C:\Program Files\cwRsyncServer\bin; date /t >> F:\syn.txt time /t >> F:\syn.txt rsync -avr --ignore-errors --force --exclude="/tmp/" --delete 192.168.0.103::test  /cygdrive/F/temp >>   F:\syn.txt date /t >> F:\syn.txt time /t >> F:\syn.txt echo . echo . echo . remote synchronous over echo . echo .

    rem pause

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

     

    linux中安全性說明

     

    一:服務端rsyncd.conf文件配置

    uid = nobody

    gid = nobody

    use chroot = no # 不使用chroot

    max connections = 4 # 最大連接數為4

    pid file = /var/run/rsyncd.pid

    lock file = /var/run/rsync.lock

    log file = /var/log/rsyncd.log # 日志記錄文件

    [inburst] # 這里是認證的模塊名,在client端需要指定

    path = /home/inburst/python/ # 需要做鏡像的目錄

    comment = BACKUP CLIENT IS SOLARIS 8 E250

    ignore errors # 可以忽略一些無關的IO錯誤

    read only = yes # 只讀

    list = no # 不允許列文件

    hosts allow=172.25.43.57 #允許連接IP

    auth users = inburst # 認證的用戶名,如果沒有這行,則表明是匿名

    secrets file = /etc/inburst.pas # 認證文件名

     

    注:

    為安全考慮,在設置服務端rsyncd.conf模塊時,最好加上auth users = inburstsecrets file = /etc/inburst.pas,密碼寫到一個文件中inburst.pas

    執行命令時:rsync -avrp /test/ [email=inburst@172.25.43.158::test]inburst@172.25.43.158::test[/email] --password-file=inburst.pas

     

    二:客戶端腳本

    rsync -avrp /test/ [email=administrator@172.25.43.58::test]administrator@172.25.43.58::test[/email] --password-file=1234567

    (表示將客戶端test目錄下文件備份到服務器test模塊下。如果將/test/放后面,表示將服務器test模塊下目錄備份帶客戶端/test/下。)

    選項說明:

    -v, --verbose 詳細模式輸出

    -q, --quiet 精簡輸出模式

    -c, --checksum 打開校驗開關,強制對文件傳輸進行校驗

    -a, --archive 歸檔模式,表示以遞歸方式傳輸文件,并保持所有文件屬性,等于-rlptgoD

    -r, --recursive 對子目錄以遞歸模式處理

    -R, --relative 使用相對路徑信息

    其他參數可以查看rsync相關手冊。

     

     


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(472) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229632  發表時間: 2008年07月04日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    dwr動態載入小結

    筆記在實際開發中用到dwr框架,一直以來,常為加載中提示用戶等待這問題困擾,經筆者研究,摸索出一個切實可行的方案,供大家參考。 實例如下: <a style="cursor:hand"  onclick="changeStatus(this);Test.invoke('${parameters}','${pageId}',callBack);"><img src='/icon.gif'></a> 函數說明: changeStatus我們將用來改變提示狀態值 Test類的invoke函數將觸發從臺數據庫取出值 然后通過回調函數callBack負責在頁面顯示出來

    頁面配置

    <script type='text/javascript' src='/dwr/interface/Test.js'></script>
    
    <script type='text/javascript' src='/dwr/engine.js'></script>
    
    <script type='text/javascript' src='/dwr/util.js'></script>
    
    <script type='text/javascript' src="/js/prototype-1.4.0.js"></script>

     

    dwr.xml

    <!DOCTYPE dwr PUBLIC
    
            "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
    
            "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
    
    <dwr>
    
        <allow>
    
    	   <create creator="new" javascript="Test">
    
                <param name="class" value="pakage.Test"/>
    
            </create>
    
            <convert converter="bean" match="pakage.Test"/>
    
        </allow>
    
    </dwr>
    回調函數
    var callBack=function(data){
    
            var pageId=data.pageId;
    
            var list=data.listEntityBean;
    
            if ($(pageId).style.display == "none") {
    
                $(pageId).style.display="block";
    
                var htmlStr = "";
    
                for (var i = 0; i < list.length; i++) { 
    
                    htmlStr +=...//這里是將list中的值取出來給一個字符串
    
                }
    
                $(pageId).innerHTML = htmlStr;
    
                return;
    
            }
    
            $(pageId).style.display="none";
    
        }
    pakage.Test類
    public class Test  {
    
        private String pageId;
    
    	private List list;
    
        public String getPageId() {
    
            return pageId;
    
        }
    
    
    
        public void setPageId(String pageId) {
    
            this.pageId = pageId;
    
        }
    
    	public String getList() {
    
            return list;
    
        }
    
    
    
        public void setList(List list) {
    
            this.list = list;
    
        }
    
       static Log log= LogFactory.getLog(Test.class);	
    
       public void invoke(String parameter,String pageId){
    
          this.setPageId(pageId);
    
    	  this.list=...//這里根據參數從數據庫里取出值來
    
    	  return this;
    
       }
    至些我們完成的dwr的編寫。
    function changeStatus(obj){
    
        var htmlStr = "";
    
        var oPopup = window.createPopup();
    
        DWREngine.setPreHook(function() {     //這是正在加載的代碼
    
            htmlStr = "<img src=\"/loading.gif\">";
    
            obj.innerHTML = htmlStr;//這里是改變傳入對象的值,是dwr正在加載時的提示,如loading,我這里是用的是圖片
    
            var oPopupBody = oPopup.document.body;
    
            oPopupBody.innerHTML = "<img src='/admin/images/spinner.gif'>";
    
            oPopup.show((Math.abs(Math.round((document.body.clientWidth-50) / 2))), Math.abs(Math.round((document.body.clientHeight-50)/ 2)), 100, 100, document.body);
    
        });
    
        DWREngine.setPostHook(function() {    //這是加載完成的代碼
    
            htmlStr = "<img src=\"/loadok.gif\">";//這里是改變傳入對象的值,是dwr加載時完成的提示,如load ok,我這里是用的是圖片
    
            obj.innerHTML = htmlStr;
    
            oPopup.hide();
    
        });
    
    }   
    
    
    以上代碼,是我在項目中抽取出來的一部份。
    小說明一下:
    var oPopup = window.createPopup();這個函數用于創建浮動頁面的loading載入提示,加載完成后將對象進行oPopup隱藏處理oPopup.hide();
    如果不須要,changeStatus這個函數完全可以這樣寫
    function changeStatus(obj){
    
        DWREngine.setPreHook(function() {     //這是正在加載的代碼
    
            obj.innerHTML = "<img src=\"/loading.gif\">";//這里是改變傳入對象的值,是dwr正在加載時的提示,如loading,我這里是用的是圖片
    
        });
    
        DWREngine.setPostHook(function() {    //這是加載完成的代碼
    
            obj.innerHTML = "<img src=\"/loadok.gif\">";//這里是改變傳入對象的值,是dwr加載時完成的提示,如load ok,我這里是用的是圖片
    
        });
    
    } 
    至此我們完美的完成了dwr加載時的提示問題,這樣也使用戶體更強,更具人性化.

    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(235) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229631  發表時間: 2008年07月17日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    linux 與adsl 共享上網
    真實機系統為windows xp,使用adsl撥號上網,虛擬機安裝linux,有一塊網卡,使用橋接模式。

    實現環境:

      1、在windows下,啟用ICS。

      選擇adsl上網撥號后的連接,屬性->高級->Internet連接共享->勾選“允許其他網絡用戶通過此計算機的internet連接共享”,家庭網絡連接選“本地連接”。

      2、在linux下,配置靜態IP。

      點主菜單->系統設置->網絡,彈出“網絡配置”,雙擊eth0,勾選“靜態設置的ip地址”,

      地址:192.168.0.2 (除192.168.0.1和255外,隨便填)

      子網掩碼: 255.255.255.0

      網關:192.168.0.1

      確定

      DNS項,主DNS填:192.168.0.1

      都填完,記得保存。

      3、重起服務

      service network restart 或者重啟linux。

      4、現在ping 一下 google.cn 看看,如果通就ok了


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(86) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229629  發表時間: 2008年07月21日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    最近由于公司要求開發一個小小的插件,用來改變文件名字
    簡單的說,就是讀取一個csv文件,里面只有兩列
    如:test.csv
    "OldName","NewName"
    "test1.eps","1.eps"
    "test2.eps","2.eps"
    "test3.tif","3.eps"
    然后用戶通過界面選擇csv文件,選擇源文件目錄,選擇目的文件目錄,選好再按一個鍵對原來文件按新的文件名輸出。

    我開始拿到蒙了,因為自己沒有搞過呀,經過查資料,自己研究,搞定。
    下面開始我們的實戰吧。

    工欲善其事,必須利其器

    首選搭建好開發環境。

    1.安裝MyEclipse 6.0
    2.安裝打包工具
       net.sf.fjep.fatjar_0.0.27.zip
       我是解壓到 MyEclipse 6.0\fjep\eclipse\plugins
        在MyEclipse 6.0\eclipse\links
     建fjep.link 里,添加 path=C:\\Program Files\\MyEclipse 6.0\\fjep
    3.重啟myeclipse
     我們的開發環境就搞定啦
     重啟后Window->Preferences可以看到 Fat Jar Preferences
        說明你安裝成功
     
    下面開始我們的項目
    1.新建Plug-in Project名字自己取Demo
      建好后可以看到結構Demo --src
                             --bin
    2.新建log4j.properties
     log4j.rootLogger=DEBUG, stdout
     log4j.appender.stdout=org.apache.log4j.ConsoleAppender
     log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
     log4j.appender.stdout.layout.ConversionPattern=%c{1} - %m%n
     log4j.logger.java.sql.PreparedStatement=DEBUG
    3.新建cvs.properties  
        csv.field.key=OldName, NewName
    4.編輯NewRenamer.java


    import java.io.File;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;

    import org.apache.commons.configuration.Configuration;
    import org.apache.commons.configuration.PropertiesConfiguration;
    import org.apache.commons.io.FileUtils;
    import org.apache.commons.lang.StringUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.custom.CLabel;
    import org.eclipse.swt.graphics.Color;
    import org.eclipse.swt.graphics.Point;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.DirectoryDialog;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.FileDialog;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Table;
    import org.eclipse.swt.widgets.TableColumn;
    import org.eclipse.swt.widgets.TableItem;
    public class Renamer
    {                                                
     private static final String CVS_PROPERTIES = "cvs.properties";
     
     Log log = LogFactory.getLog(Renamer.class);
     private Shell sShell = null;
     private Button btnSourceDir = null;
     private CLabel labSourceDir = null;
     
     private Button btnDestinationDir = null;
     private CLabel labDestinationDir = null;
     
     private Button btnCSVFile = null;
     private CLabel labCSVFile = null;
     
     String openDirPathFlag = "openDirPath";  //  @jve:decl-index=0:
     private Table tabPreview = null;
     private Button processIt = null;
     
     //private Button restoreIt = null;
     //private Button flashRestore = null;
     int runTime = 1000 * 10;
     
     private void createSShell() {
      GridData gridData = new GridData();
     
      gridData.horizontalSpan = 7;
      gridData.verticalAlignment = GridData.FILL;
     
      gridData.verticalSpan = 3;
      gridData.grabExcessVerticalSpace = true;
      gridData.horizontalAlignment = GridData.FILL;
     
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 8;
     
      sShell = new Shell();
      sShell.setText("Shell");
      sShell.setLayout(gridLayout);
      sShell.setSize(new Point(800, 500));
     
     
      btnCSVFile = new Button(sShell, SWT.NONE);
      btnCSVFile.setText("CSV");
      btnCSVFile.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
       public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
        //清掉以前的顯示結果
        tabPreview.removeAll();
        //path part
        String openDirPath = (String)btnCSVFile.getData(openDirPathFlag);
        FileDialog dd = new FileDialog(sShell, SWT.NONE);//用來顯示一個目錄對話
        dd.setFilterPath(openDirPath);
        dd.setText("CVS file");
        String cvsPath = dd.open();
        cvsPath = cvsPath == null ? "" : cvsPath;
        btnCSVFile.setData(openDirPathFlag,cvsPath);
           labCSVFile.setText(cvsPath);
           if(StringUtils.isEmpty(cvsPath)) return;
         //得到csv文件
       
        String csvDir=StringUtils.substringBeforeLast(cvsPath, "\\");
        String csvFileName=StringUtils.substringAfterLast(cvsPath, "\\");
        String csvFileNameNotSuffix=StringUtils.replace(csvFileName, ".csv", "");
        log.debug(csvDir);
        log.debug(csvFileNameNotSuffix);
        try {
         Configuration config = new PropertiesConfiguration(CVS_PROPERTIES);
         String[] aryFields = config.getStringArray("csv.field.key"); 
        
         // 加載驅動
         Class.forName("org.relique.jdbc.csv.CsvDriver");

         // 定位文件夾位置

         Connection conn = DriverManager
           .getConnection("jdbc:relique:csv:"+csvDir);

         Statement stmt = conn.createStatement();

         // 注意 csvFileNameNotSuffix 就是cvs文件
        
         ResultSet results = stmt
           .executeQuery("SELECT * FROM "+csvFileNameNotSuffix);

         while (results.next()) {
          String showname = results.getString(aryFields[0]);
                String destName = results.getString(aryFields[1]);
                TableItem item = new TableItem(tabPreview, SWT.NONE);
                item.setText(0,showname);
             TabItemData itemData = new TabItemData(cvsPath,"",showname,"",destName);
             item.setData("itemData",itemData);
                item.setText(1,destName); 
         }
         results.close();
         stmt.close();
         conn.close();

        } catch (Exception e1) {

         log.debug(e1);
        }

       }
      });
      labCSVFile = new CLabel(sShell, SWT.NONE);
      labCSVFile.setText("please choose CSV");
     
     
     
     
     
      btnSourceDir = new Button(sShell, SWT.NONE);
      btnSourceDir.setText("source");
      btnSourceDir
      .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
       public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
        String csvFile = (String)btnCSVFile.getData(openDirPathFlag);
        if(StringUtils.isEmpty(csvFile)) return;//必須先有csv文件

        //path part
        String openDirPath = (String)btnSourceDir.getData(openDirPathFlag);
       
        DirectoryDialog dd = new DirectoryDialog(sShell, SWT.NONE);//用來顯示一個目錄對話
        dd.setFilterPath(openDirPath);
        dd.setText("Souce Dir");
        String sourcePath = dd.open();
        sourcePath = sourcePath == null ? "" : sourcePath;
       
        btnSourceDir.setData(openDirPathFlag,sourcePath);
           labSourceDir.setText(sourcePath);
          
                    int tabLength = tabPreview.getItems().length;
       
        for(int i=0;i<tabLength;i++){
         TableItem item = tabPreview.getItem(i);
        
         TabItemData itemData = (TabItemData)item.getData("itemData");
         itemData.setSourceDir(sourcePath+"\\");//把源目錄加進去
        
         item.setData("itemData",itemData);

         System.out.println(i+":" +tabPreview.getItems().length + "\n" + itemData);
         if(new File(itemData.getSourceFilePath()).exists()){
          item.setBackground(new Color( sShell.getDisplay(), 0, 255, 128 ));
         }
        
        }
       
       
       }
      });
     
     
     
      labSourceDir = new CLabel(sShell, SWT.NONE);
      labSourceDir.setText("please choose directory");
     
      btnDestinationDir = new Button(sShell, SWT.NONE);
      btnDestinationDir.setText("destination");
      btnDestinationDir.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
       public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
        String openDirPath = (String)btnDestinationDir.getData(openDirPathFlag);
       
        DirectoryDialog dd = new DirectoryDialog(sShell, SWT.NONE);
        dd.setFilterPath(openDirPath);
        dd.setText("destination dir");
        String path = dd.open();
        btnDestinationDir.setData(openDirPathFlag,path);
        labDestinationDir.setText(path);
       }
      });
      labDestinationDir = new CLabel(sShell, SWT.NONE);
      labDestinationDir.setText("please choose directory");
     
     
     
     
     
     
      processIt = new Button(sShell, SWT.NONE);
      processIt.setText(" process it ");
      processIt.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
       public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
        //得到目的路徑
        String descPath = (String)btnDestinationDir.getData(openDirPathFlag);
        if(StringUtils.isEmpty(descPath)) return;
       
        int tabLength = tabPreview.getItems().length;
        descPath += "\\";
        for(int i=0;i<tabLength;i++){
         TableItem item = tabPreview.getItem(i);
         TabItemData itemData = (TabItemData)item.getData("itemData");
        
         itemData.setDestinationDir(descPath);
        
         System.out.println(i+":" +tabPreview.getItems().length + "\n" + itemData);
         if(new File(itemData.getSourceFilePath()).exists()){
         try {
          FileUtils.copyFile(new File(itemData.getSourceFilePath()),new File(itemData.getDestinationFilePath()));
          item.setBackground(new Color( sShell.getDisplay(), 184, 109, 109 ));
         } catch (IOException e1) {
          System.out.println("e1:" + e1);
         }
         }
        }
       }
      });
     

      tabPreview = new Table(sShell, SWT.NONE);
      tabPreview.setHeaderVisible(true);
      tabPreview.setLayoutData(gridData);
      tabPreview.setLinesVisible(true);
     
      TableColumn colSource = new TableColumn(tabPreview, SWT.NONE);
      colSource.setWidth(350);
      colSource.setText("source");
     
      TableColumn colDestination = new TableColumn(tabPreview, SWT.NONE);
      colDestination.setWidth(350);
      colDestination.setText("destination");
     
     }
     
     
        public static void main(String[] args)
        {
        
         Display display = Display.getDefault();
         Renamer thisClass = new Renamer();
      thisClass.createSShell();
      thisClass.sShell.open();

      while (!thisClass.sShell.isDisposed()) {
       if (!display.readAndDispatch())
        display.sleep();
      }
      display.dispose();
     
         }
    }

     

    5.編輯BaseObject.java


    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.apache.commons.lang.builder.ToStringStyle;
    import org.apache.commons.lang.builder.ToStringBuilder;
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    import java.io.Serializable;

    public class BaseObject implements Serializable {

        public static final Log log = LogFactory.getLog(BaseObject.class);

        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
        }

        public boolean equals(Object o) {
            return EqualsBuilder.reflectionEquals(this, o);
        }

        public int hashCode() {
            return HashCodeBuilder.reflectionHashCode(this);
        }


    }
    6.編輯TabItemData.java


    public class TabItemData extends BaseObject{
     String sourceDir = "";
     String csvFile = "";
     String fileInSourceDir = "";
     String destinationDir = "";
     String fileInDestinationDir = "";
     
     
     public TabItemData(String csvFile,String sourceDir,
       String fileInSourceDir,
       String destinationDir,
       String fileInDestinationDir){
      this.csvFile = csvFile;
      this.sourceDir = sourceDir;
      this.fileInSourceDir = fileInSourceDir;
      this.destinationDir = destinationDir;
      this.fileInDestinationDir = fileInDestinationDir;
     
     }
     
     
     public String getCsvFile() {
      return csvFile;
     }

     public void setCsvFile(String csvFile) {
      this.csvFile = csvFile;
     }

     public String getSourceFilePath(){
      return this.getSourceDir() + this.getFileInSourceDir();
     }
     
     public String getDestinationFilePath(){
      return this.getDestinationDir() + this.getFileInDestinationDir();
     }
     
     public String getDestinationDir() {
      return destinationDir;
     }
     public void setDestinationDir(String destinationDir) {
      this.destinationDir = destinationDir;
     }
     public String getFileInDestinationDir() {
      return fileInDestinationDir;
     }
     public void setFileInDestinationDir(String fileInDestinationDir) {
      this.fileInDestinationDir = fileInDestinationDir;
     }
     public String getFileInSourceDir() {
      return fileInSourceDir;
     }
     public void setFileInSourceDir(String fileInSourceDir) {
      this.fileInSourceDir = fileInSourceDir;
     }
     public String getSourceDir() {
      return sourceDir;
     }
     public void setSourceDir(String sourceDir) {
      this.sourceDir = sourceDir;
     }
     
     

    }


    7.上面我們把一切都編好了
      然后選擇項目->右健->Fat jar->選擇main class [NewRenamer] ->finish就生成夾包了
    8.編輯批處理文件 
    run.bat 里面加
    start javaw -jar Demo_fat.jar

    即可運行啦

    說明:
    jdk 1.42
    這是本項目必須的jar包
    commons-collections-3.0.jar
    commons-configuration-1.5.jar
    commons-io-1.2.jar
    commons-lang-2.4.jar
    commons-logging.jar
    csvjdbc.jar
    log4j-1.2.9.jar

     


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(142) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229627  發表時間: 2008年07月23日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    import org.eclipse.swt.SWT;
    import org.eclipse.swt.events.PaintEvent;
    import org.eclipse.swt.events.PaintListener;
    import org.eclipse.swt.events.SelectionAdapter;
    import org.eclipse.swt.events.SelectionEvent;
    import org.eclipse.swt.graphics.Image;
    import org.eclipse.swt.layout.FormAttachment;
    import org.eclipse.swt.layout.FormData;
    import org.eclipse.swt.layout.FormLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Canvas;
    import org.eclipse.swt.widgets.Combo;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.FileDialog;
    import org.eclipse.swt.widgets.Group;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.List;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Text;
    
    public class DogShowRegistrationWindow {
    	/*
    	 * 參考文章
    	 * http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html
    	 * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui1/index.html
    	 * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui2/index.html
    	 * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui3/index.html
    	 * http://www-128.ibm.com/developerworks/cn/opensource/os-swingswt/
    	 * http://www.tkk7.com/fortune/archive/2006/03/09/34463.html
    	 */	
    	Image dogImage;
    	Text dogNameText;
    	Combo dogBreedCombo;
    	Canvas dogPhoto;
    	List categories;
    	Text nameText;
    	Text phoneText;
    
    	public static void main(String[] args) {
    		Display display = new Display();
    		Shell shell = new DogShowRegistrationWindow().createShell(display);
    		shell.open();
    		while (!shell.isDisposed()) {
    			if (!display.readAndDispatch())
    				display.sleep();
    		}
    	}
    	
    	public Shell createShell(final Display display) {
    		final Shell shell = new Shell(display);//通用窗口 
    		FormLayout layout = new FormLayout();//布局管理器 
    		layout.marginWidth = 5;
    		layout.marginHeight = 5;
    		shell.setLayout(layout);
    		shell.setText("Dog Show Entry");
    	    //****************************定義布局所要用的資源開始****************************
    		//定義dog name標簽
    		Label dogName = new Label(shell, SWT.NONE);//顯示靜態文本 
    		dogName.setText("Dog's Name:");
    		//定義dog name的文本輸入框
    		dogNameText = new Text(shell, SWT.SINGLE | SWT.BORDER);//文本輸入 
    		//定義dog greed標簽
    		Label dogBreed = new Label(shell, SWT.NONE);
    		dogBreed.setText("Breed:");
    		//定義一個dog greed多選框
    		dogBreedCombo = new Combo(shell, SWT.NONE);
    		dogBreedCombo.setItems(new String[] { "Collie", "Pitbull", "Poodle","Scottie", "Black Lab" });//從一個下拉列表中選擇
    		//定義photo標簽
    		Label photo = new Label(shell, SWT.NONE);
    		photo.setText("Photo:");
    		//定義photo顯示域
    		dogPhoto = new Canvas(shell, SWT.BORDER);//繪圖區域;可能用于定制控件 
    		//定義Photo Browse按鈕
    		Button browse = new Button(shell, SWT.PUSH);
    		browse.setText("Browse...");
    		//定義Photo Delete按鈕
    		Button delete = new Button(shell, SWT.PUSH);//簡單按下具有文本的按鈕 
    		delete.setText("Delete");
    		//定義分類標簽
    		Label cats = new Label(shell, SWT.NONE);
    		cats.setText("Categories");
    		//定義分類List
    		categories = new List(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);//從條目列表中進行選擇 
    		categories.setItems(new String[] { "Best of Breed", "Prettiest Female",
    				"Handsomest Male", "Best Dressed", "Fluffiest Ears",
    				"Most Colors", "Best Performer", "Loudest Bark",
    				"Best Behaved", "Prettiest Eyes", "Most Hair", "Longest Tail",
    				"Cutest Trick" });
    		//定義一個組
    		Group ownerInfo = new Group(shell, SWT.NONE);//其他控件的有邊界和標題的通用容器 
    		ownerInfo.setText("Owner Info");
    		FormLayout ownerLayout = new FormLayout();//布局管理器 
    		ownerLayout.marginWidth = 5;
    		ownerLayout.marginHeight = 5;
    		ownerInfo.setLayout(ownerLayout);
    		
    		//定義Enter按鈕
    		Button enter = new Button(shell, SWT.PUSH);
    		enter.setText("Enter");
    		//****************************定義布局所要用的資源結束****************************
    		FormData data = new FormData();
    		data.top = new FormAttachment(dogNameText, 0, SWT.CENTER);
    		dogName.setLayoutData(data);//定義dogName與dogNameText的中心位置對齊
    		
    		data = new FormData();
    		data.left = new FormAttachment(dogName, 5);
    		data.right = new FormAttachment(100, 0);
    		dogNameText.setLayoutData(data);//定義dogNameText左邊距dogName5個點數的偏移  右邊100%填充
    		
    		data = new FormData();
    		data.top = new FormAttachment(dogBreedCombo, 0, SWT.CENTER);
    		dogBreed.setLayoutData(data);
    		//定義dogBreed項部距dogBreedCombo 0個點數的偏移 與dogBreedCombo標簽的中心位置對齊 
    		
    		data = new FormData();
    		data.top = new FormAttachment(dogNameText, 5);
    		data.left = new FormAttachment(dogNameText, 0, SWT.LEFT);
    		data.right = new FormAttachment(categories, -5);
    		dogBreedCombo.setLayoutData(data);
    		//定義dogBreedCombo項部距dogNameText 5個點數的偏移
    		//定義dogBreedCombo左邊與 dogNameText的左邊對齊
    		//定義dogBreedCombo右邊距 categories左邊5個點數的偏移
    		
    		data = new FormData(80, 80);
    		data.top = new FormAttachment(dogBreedCombo, 5);
    		data.left = new FormAttachment(dogNameText, 0, SWT.LEFT);
    		data.right = new FormAttachment(categories, -5);
    		data.bottom = new FormAttachment(ownerInfo, -5);
    		dogPhoto.setLayoutData(data);
    		//定義dogPhoto大小為80X80
    		//定義dogPhoto頂邊與dogBreedCombo底邊點數的偏移
    		//定義dogPhoto左邊與dogNameText左邊對齊
    		//定義dogPhoto右邊距categories 5個點數的偏移
    		//定義dogPhoto底邊距ownerInfo 5個點數的偏移
    		dogPhoto.addPaintListener(new PaintListener() {
    			public void paintControl(final PaintEvent event) {
    				if (dogImage != null) {
    					event.gc.drawImage(dogImage, 0, 0);
    				}
    			}
    		});
    		
    		data = new FormData();
    		data.top = new FormAttachment(dogPhoto,0, SWT.TOP);
    		photo.setLayoutData(data);
    		//定義photo頂邊與 dogPhoto的頂邊對齊
    		
    		data = new FormData();
    		data.top = new FormAttachment(photo, 5);
    		data.right = new FormAttachment(dogPhoto, -5);
    		browse.setLayoutData(data);
    		//定義photo頂邊距 photo 5個點數的偏移
    		//定義photo右邊距 dogPhoto 5個點數的偏移
    		browse.addSelectionListener(new SelectionAdapter() {
    			public void widgetSelected(SelectionEvent event) {
    				String fileName = new FileDialog(shell).open();//用來顯示一個文件對話
    				if (fileName != null) {
    					dogImage = new Image(display, fileName);
    				}
    			}
    		});
    		
    		data = new FormData();
    		data.top = new FormAttachment(browse, 5);
    		data.left = new FormAttachment(browse, 0, SWT.LEFT);
    		data.right = new FormAttachment(dogPhoto, -5);
    		delete.setLayoutData(data);
    		//定義delete頂邊距 browse 5個點數的偏移
    		//定義delete左邊與 browse 左邊對齊
    		//定義delete右邊距 dogPhoto 5個點數的偏移
    		delete.addSelectionListener(new SelectionAdapter() {
    			public void widgetSelected(SelectionEvent event) {
    				if (dogImage != null) {
    					dogImage.dispose();
    					dogImage = null;
    					dogPhoto.redraw();
    				}
    			}
    		});
    		
    		data = new FormData(90, 140);
    		data.top = new FormAttachment(dogPhoto, 0, SWT.TOP);
    		data.right = new FormAttachment(100, 0);
    		data.bottom = new FormAttachment(enter, -5);
    		categories.setLayoutData(data);
    		//定義categories頂邊與 dogPhoto的頂邊對齊
    		//定義categories右邊100% 填充
    		//定義categories底邊距底邊父組件 5個點數的偏移 
    		
    		data = new FormData();
    		data.bottom = new FormAttachment(categories, -5);
    		data.left = new FormAttachment(categories, 0, SWT.CENTER);
    		cats.setLayoutData(data);
    		//定義cats底邊與 categories的底邊 5個點數的偏移
    		//定義cats左邊與 categories 的中心對齊
    		
    		data = new FormData();
    		data.right = new FormAttachment(100, 0);
    		data.bottom = new FormAttachment(100, 0);
    		enter.setLayoutData(data);
    		enter.addSelectionListener(new SelectionAdapter() {
    			public void widgetSelected(SelectionEvent event) {
    				System.out.println("\nDog Name: " + dogNameText.getText());
    				System.out.println("Dog Breed: " + dogBreedCombo.getText());
    				System.out.println("Owner Name: " + nameText.getText());
    				System.out.println("Owner Phone: " + phoneText.getText());
    				System.out.println("Categories:");
    				String cats[] = categories.getSelection();
    				for (int i = 0; i < cats.length; i++) {
    					System.out.println("\t" + cats[i]);
    				}
    			}
    		});
    		
    		data = new FormData();
    		data.bottom = new FormAttachment(enter, -5);
    		data.left = new FormAttachment(0, 0);
    		data.right = new FormAttachment(categories, -5);
    		ownerInfo.setLayoutData(data);
    		
    		Label name = new Label(ownerInfo, SWT.NULL);
    		name.setText("Name:");
    		
    		Label phone = new Label(ownerInfo, SWT.PUSH);
    		phone.setText("Phone:");
    		
    		nameText = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
    		phoneText = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
    		
    		data = new FormData();
    		data.top = new FormAttachment(nameText, 0, SWT.CENTER);
    		name.setLayoutData(data);
    		
    		data = new FormData();
    		data.top = new FormAttachment(phoneText, 0, SWT.CENTER);
    		phone.setLayoutData(data);
    		
    		data = new FormData();
    		data.left = new FormAttachment(phone, 5);
    		data.right = new FormAttachment(100, 0);
    		nameText.setLayoutData(data);
    		
    		data = new FormData();
    		data.left = new FormAttachment(nameText, 0, SWT.LEFT);
    		data.right = new FormAttachment(100, 0);
    		data.top = new FormAttachment(55, 0);
    		phoneText.setLayoutData(data);
    		
    		shell.pack();
    		
    		return shell;
    	}	
    }
    

    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(226) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229625  發表時間: 2008年08月04日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    swt學習小結
    Widget —— 基本的 SWT GUI 組件
    Control —— 擁有操作系統的對等物的窗口小部件
    Composite —— 包含其他控件的控件
    Item —— 其他控件包含的窗口小部件(該控件可能不是復合控件),比如列表和表

    標準的SWT布局類
    FillLayout:在容器中以相同的大小單行或單列的排列組件
    RowLayout:以單行或多行的方式使用幾個選項(fill,wrap,spacing,justify,type)定制組件的排列方式
    GridLayout:類似于swing的GridLayout的方式以格子的方式排列組件
    FormLayout(SWT 2.0的新特性):通過定義組件四個邊的“粘貼”位置來排列組件,被引用的相對的組件可以父組件,也可以是同一容器中的其它組件。

    /*
     * 參考文章
     * http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html
     * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui1/index.html
     * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui2/index.html
     * http://www.ibm.com/developerworks/cn/linux/opensource/os-ecgui3/index.html
     * http://www-128.ibm.com/developerworks/cn/opensource/os-swingswt/
     * http://www.tkk7.com/fortune/archive/2006/03/09/34463.html
     */ 
     
     布局實施
    1.首先定義窗口和它的空白邊
    Display.getDefault().dispose();  //移去平臺核心啟動畫面
            display = new Display();
            shell = new Shell(display, SWT.TITLE);
            FormLayout layout = new FormLayout();
            layout.marginHeight = 10;
            layout.marginWidth = 20;
            shell.setLayout(layout);
            shell.setText("用戶登錄");

    2.創建窗口上的元素,其中下面的兩個button由一個使用RowLayout的組件來包容。
            name = new Label(shell, SWT.NONE);
            name.setText("用戶名");
            nameText = new Text(shell, SWT.SINGLE | SWT.BORDER);
            pass = new Label(shell, SWT.NONE);
            pass.setText("密碼");
            passText = new Text(shell, SWT.SINGLE | SWT.BORDER);
            passText.setEchoChar('*');
            passText.setTabs(2);
            bottom = new Composite(shell, SWT.NONE);
            RowLayout rowLayout = new RowLayout();
            rowLayout.justify = true;  //justify定義組件在容器中分散開,效果類似于swing的FlowLayout
            bottom.setLayout(rowLayout);

    3.定義name標簽的位置。它的頂邊離父組件(窗口shell)的空白邊距離是父組件clientArea(除空白邊以外的空間)高度(height)的15%,偏移的點數(points)為0。
    FormData data = new FormData();
            data.top = new FormAttachment(15, 0);
            name.setLayoutData(data);

    4.定義name文本輸入的位置。它的頂邊在name標簽的中心位置(這不是正確的表達,但程序是這樣解釋,事實上它的中心位置與name標簽在同一條水平線上),左邊距name標簽的右邊有10個點。
    data = new FormData();
            data.top = new FormAttachment(name, 0, SWT.CENTER);
            data.left = new FormAttachment(name, 10, SWT.RIGHT);
            nameText.setLayoutData(data);

    5.定義pass標簽的位置。它的頂邊距name標簽的底邊有10個點數的偏移。
    data = new FormData();
            data.top = new FormAttachment(name, 10, SWT.BOTTOM);
            pass.setLayoutData(data);

    6.定義pass文本輸入的位置。它的頂邊在name標簽的中心位置(同上),左邊與name文本框的左邊對齊。
    data = new FormData();
            data.top = new FormAttachment(pass, 0, SWT.CENTER);
            data.left = new FormAttachment(nameText, 0, SWT.LEFT);
            passText.setLayoutData(data);

    7.定義bottom組件的位置。它的頂邊距pass標簽的底邊15個點數,左邊與pass標簽的左邊對齊,右邊與pass文本輸入的右邊對齊。
            data = new FormData();
            data.top = new FormAttachment(pass, 15, SWT.BOTTOM);
            data.left = new FormAttachment(pass, 0, SWT.LEFT);
            data.right = new FormAttachment(passText, 0, SWT.RIGHT);
            bottom.setLayoutData(data);

    完整的源碼
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.events.SelectionAdapter;
    import org.eclipse.swt.events.SelectionEvent;
    import org.eclipse.swt.graphics.Rectangle;
    import org.eclipse.swt.layout.FormAttachment;
    import org.eclipse.swt.layout.FormData;
    import org.eclipse.swt.layout.FormLayout;
    import org.eclipse.swt.layout.RowLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Text;

    import cn.com.efly.clientframe.core.Hook;

    /**
     * @author efly
     * @version 1.0.0,11/22/02
     */
    public final class LoginUI {
        private Display display;
        private Shell shell;
        private Composite bottom;
        private Label name;
        private Label pass;
        private Text nameText;
        private Text passText;
        private Button ok;
        private Button exit;
        private Rectangle clientArea;
        private RootHook rootHook;

        public LoginUI(Hook hook) {
            rootHook = (RootHook) hook;
        }

        /**
         * 顯示登陸界面
         */
        public void show() {
            Display.getDefault().dispose();
            display = new Display();
            clientArea = display.getClientArea();
            shell = new Shell(display, SWT.TITLE);
            FormLayout layout = new FormLayout();
            layout.marginHeight = 10;
            layout.marginWidth = 20;
            shell.setLayout(layout);
            shell.setText("用戶登錄");

            name = new Label(shell, SWT.NONE);
            name.setText("用戶名");
            nameText = new Text(shell, SWT.SINGLE | SWT.BORDER);
            pass = new Label(shell, SWT.NONE);
            pass.setText("密碼");
            passText = new Text(shell, SWT.SINGLE | SWT.BORDER);
            passText.setEchoChar('*');
            passText.setTabs(2);
            bottom = new Composite(shell, SWT.NONE);
            RowLayout rowLayout = new RowLayout();
            rowLayout.justify = true;
            bottom.setLayout(rowLayout);
            ok = new Button(bottom, SWT.PUSH);
            ok.setText("確定");
            ok.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent event) {
                    ok();
                }
            });
            exit = new Button(bottom, SWT.PUSH);
            exit.setText("取消");
            exit.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent event) {
                    cancel();
                }
            });

            FormData data = new FormData();
            data.top = new FormAttachment(15, 0);
            name.setLayoutData(data);

            data = new FormData();
            data.top = new FormAttachment(name, 0, SWT.CENTER);
            data.left = new FormAttachment(name, 10, SWT.RIGHT);
            nameText.setLayoutData(data);

            data = new FormData();
            data.top = new FormAttachment(name, 10, SWT.BOTTOM);
            pass.setLayoutData(data);

            data = new FormData();
            data.top = new FormAttachment(pass, 0, SWT.CENTER);
            data.left = new FormAttachment(nameText, 0, SWT.LEFT);
            passText.setLayoutData(data);

            data = new FormData();
            data.top = new FormAttachment(pass, 15, SWT.BOTTOM);
            data.left = new FormAttachment(pass, 0, SWT.LEFT);
            data.right = new FormAttachment(passText, 0, SWT.RIGHT);
            bottom.setLayoutData(data);

            shell.pack();
            Rectangle shellBounds = shell.getBounds();
            shell.setLocation(
                (clientArea.width - shellBounds.width) / 2,
                (clientArea.height - shellBounds.height) / 2);

            shell.open();

            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }
        }

        private void dispose() {
            display.dispose();

        }

        private void cancel() {
            dispose();
        }

        private void ok() {
            verify();
        }

        private void verify() {
            rootHook.runPlatform();
        }

            public static void main(String[]){
                    new LoginUI(null).show();
            }
    }


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(305) | 評論 (0)編輯 收藏


    作者: beauty9235  鏈接:http://beauty9235.javaeye.com/blog/229622  發表時間: 2008年08月08日

    聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

    webwork處理編碼webwork.properties 設置你的缺省 locale和編碼方案
     webwork.locale=en_US
     webwork.i18n.encoding=UTF-8
    如果使用freemarker 還要設置freemarker.properties
     locale=en_US
     default_encoding=UTF-8
    網頁上設置編碼
     1、JSP文件用支持UTF-8的文字編輯器編輯,如EditPlus、UltraEdit,并把原來ascii轉換成utf-8(菜單里有)。
     2、JSP文件頭改成:
     <%@ page contentType="text/html; charset=UTF-8" language="java"  import="java.sql.*"%>
     3、html文件
     <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    數據庫
     1、mysql配置文件:修改mysql在windows\my.ini里default-character-set=utf-8
     2、mysql里數據庫和表也都設為utf8_unicode_ci
     3、數據庫連結:jdbc:mysql://localhost/mydb?useUnicode=true&characterEncoding=utf-8
    屬性文件 
    native2ascii -encoding UTF8 ApplicationResources_xx.properties ApplicationResources_zh.properties 
    過濾器
     EncodingFilter.java
      public class EncodingFilter implements Filter {
          public void init(FilterConfig cong) {
        //  do nothing
       }

       public void doFilter(ServletRequest srequest, ServletResponse sresponse,
         FilterChain chain) {
        try{
         //編碼
         srequest.setCharacterEncoding("UTF-8");
         //繼續請求
         chain.doFilter(srequest, sresponse);
        }catch(Exception e){
         e.printStackTrace();
        }
       }

       public void destroy() {
        //do nothing
       }
      }
     web.xml
     <filter>
      <filter-name>encodingfilter</filter-name>
      <filter-class>fr.simatai.util.application.EncodingFilter</filter-class>
     </filter>
     <filter-mapping>
      <filter-name>encodingfilter</filter-name>
      <url-pattern>/*</url-pattern>
     </filter-mapping> 
    數據庫字符編碼轉化(己存在的表)
    ALTER TABLE test CONVERT TO CHARACTER SET UTF8 


    本文的討論也很精彩,瀏覽討論>>


    JavaEye推薦



    posted @ 2008-08-18 17:04 beauty9235 閱讀(103) | 評論 (0)編輯 收藏

    僅列出標題
    共3頁: 上一頁 1 2 3 下一頁 
    主站蜘蛛池模板: 日韩成人毛片高清视频免费看| 香蕉免费一级视频在线观看| 亚洲精品免费视频| 四虎永久成人免费| 亚洲精品无码久久久久YW| 永久免费av无码不卡在线观看| 亚洲欧洲免费无码| 97se亚洲综合在线| 18女人毛片水真多免费| 久久久久亚洲AV无码专区体验| 亚洲制服丝袜精品久久| 青青青免费国产在线视频小草| 无码人妻久久一区二区三区免费丨| 毛片a级毛片免费播放100| 日韩亚洲产在线观看| 99久久免费国产精品特黄| 亚洲高清一区二区三区| 国产网站在线免费观看| 特级毛片免费播放| 亚洲中文字幕无码久久精品1 | 亚洲福利一区二区| 亚洲免费福利视频| 日韩亚洲不卡在线视频中文字幕在线观看 | 皇色在线视频免费网站| 亚洲色大网站WWW永久网站| 97无码免费人妻超级碰碰夜夜| www亚洲一级视频com| 国产美女视频免费观看的网站| 222www在线观看免费| 亚洲AV无码精品蜜桃| 在线观看免费污视频| 一区二区三区精品高清视频免费在线播放| 97人妻精品全国免费视频| 亚洲午夜精品一区二区| 在线中文高清资源免费观看| 曰批免费视频播放在线看片二| 无码人妻一区二区三区免费手机 | 又硬又粗又长又爽免费看| 国产精品亚洲美女久久久| a级毛片免费完整视频| 亚洲啪啪免费视频|