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

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

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

    隨筆-25  評論-6  文章-0  trackbacks-0
     
    ActionMapping類
    將特定請求映射到特定Action的相關信息存儲在ActionMapping中,ActionServelt將ActionMapping傳送到Action類的execute()方法,Action將使用ActionMapping的findForward()方法,此方法返回一個指定名稱的ActionForward,這樣Action就完成了本地轉發。若沒有找到具體的ActionForward,就返回一個null.
    ActionMapping的方法:
    public ExceptionConfig findException(Class type) ,查找異常對象
    public ActionForward findForward(String name) 可在映射中動態添加ActionForward:
    public String[] findForwards()找到一個Action可以使用的actionForward列表
    public ActionForward getInputForward() ?得到本action的輸入ActionForard.
    ActionMapping繼承于org.apache.struts.config.ActionConfig

    Action類
    Action類真正實現應用程序的事務邏輯,它們負責處理請求。在收到請求后,ActionServlet會:
    1.為這個請求選擇適當的Action
    2.如果需要,創建Action的一個實例
    3.調用Action的execute()方法
    如果ActionServlet不能找到有效的映射,它會調用默認的Action類(在配置文件中定義)。如果找到了ActionServlet將適當的ActionMapping類轉發給Action,這個Action使用ActionMapping找到本地轉發,然后獲得并設置ActionMapping屬性。根據servlet的環境和被覆蓋的execute ()方法的簽名,ActionServlet也會傳送ServletRequest對象或HttpServletRequest對象。
    所有Action類都擴展org.apache.struts.action.Action類,并且覆蓋類中定義的某一個execute ()方法。有兩個execute ()方法:
    處理非HTTP(一般的)請求:
    public ActionForward execute (ActionMapping action,
    Acionform form,
    ServletRequest request,
    ServletResponse response)
    ? ?throws java.lang.Exception
    處理HTTP請求:
    public ActionForward execute (ActionMapping action,
    Acionform form,
    HttpServletRequest request,
    HttpServletResponse response)
    ? ?throws java.lang.Exception
    Action類必須以”線程安全”的方式進行編程,因為控制器會令多個同時發生的請求共享同一個實例,相應的,在設計Action類時就需要注意以下幾點:
    不能使用實例或靜態變量存儲特定請求的狀態信息,它們會在同一個操作中共享跨越請求的全局資源
    如果要訪問的資源(如JavaBeans和會話變量)在并行訪問時需要進行保護,那么訪問就要進行同步
    Action類的方法
    除了execute ()方法外,還有以下方法:
    可以獲得或設置與請求相關聯的區域:
    public Locale getLocale(HttpServletRequest request)
    public void setLocale(HttpServletRequest request,Locale locale)
    為應用程序獲得消息資源:
    protected MessageResources getResources(HttpServletRequest request)
    protected MessageResources getResources(HttpServletRequest request,String key)
    檢查用戶是否點擊表單上的”取消”鍵,如果是,將返回true:
    public Boolean isCancelled(HttpServletRequest request)
    當應用程序發生錯誤時,Action類能夠使用下面方法存儲錯誤信息:
    public void saveErrors(HttpServletRequest request,ActionErrors errors)
    public void saveMessages(HttpServletRequest request,ActionMessages messages)
    ActionError實例被用來存儲錯誤信息,這個方法在錯誤關鍵字下的請求屬性列表中存儲ActionError對象。通過使用在struts標記庫中定義的自定義標記,JSP頁能夠顯示這些錯誤信息。ActionMessages 用來存儲一些提示信息,不是錯誤,在jsp頁面可以使用標記現實這些提示信息。
    請求有效性處理,使用令牌可以有效的防止重復提交。
    protected String generateToken(HttpServletRequest request) 創建一個令牌.
    protected boolean isTokenValid(HttpServletRequest request) 檢查令牌是否有效
    protected boolean isTokenValid(HttpServletRequest request,Boolean reset) 檢查令牌是否有效,并且重置令牌(如果reset 是true)
    protected void resetToken(HttpServletRequest request) 重置令牌
    protected void saveToken(HttpServletRequest request) 添加令牌
    獲取數據庫連接
    protected DataSource getDataSource(HttpServletRequest request)
    protected DataSource getDataSource(HttpServletRequest request, String key)
    其他的
    ActionServlet getServlet() ?可以獲得本action的配置信息.

    DispatchAction類
    DispatchAction是Action的子類,主要功能可以實現,動態的方法調用。例如action中有一個方法update(ActionMapping mapping, Actionform form, HttpServletRequest request, HttpServletResponse response), 可以通過 saveSubscription.do?method=update來調用update方法。這個類不需要我們實現其他方法,我們只要實現 XXX(ActionMapping mapping, Actionform form, HttpServletRequest request, HttpServletResponse response)就可以了。
    在http://www.chinajavaworld.net/forum/topic.cgi?forum=48&topic=1166&show=150和
    http://www.chinajavaworld.net/forum/topic.cgi?forum=48&topic=1129有對DispatchAction和LookupDispatchAction的詳細介紹

    SwitchAction類
    SwitchAction是Action的子類,主要功能是將請求在不同的模塊之間轉發。對于大的項目很有用。具體看http://www.chinajavaworld.net/forum/topic.cgi?forum=48&topic=1029&show=0

    Actionform類
    假設用戶在應用程序中為每個表單都創建了一個Actionform bean,對于每個在struts-config.xml文件中定義的bean,框架在調用Action類的execute()方法之前會進行以下操作:
    在相關聯的關鍵字下,它檢查用于適當類的bean實例的用戶會話(或請求),如果在會話(或請求)中沒有可用的bean,它就會自動創建一個新的bean并添加到用戶的會話(或請求)中。至于是在會話還是請求取決于struts-config.xml 中Action 的scope屬性。在創建Actionform的時候,系統會將請求中的值,進行相應的類型轉換以后對Actionform進行初始化。
    對于請求中每個與bean屬性名稱對應的參數,Action調用相應的設置方法。
    當Action execute()被調用時,最新的Actionform bean傳送給它,參數值就可以立即使用了。
    Actionform類擴展org.apache.struts.action.Actionform類,程序開發人員創建的bean能夠包含額外的屬性,而且ActionServlet可能使用反射(允許從已加載的對象中回收信息)訪問它。
    Actionform類提供了另一種處理錯誤的手段,提供兩個方法:
    Public ActionErrors validate(ActionMappin mapping, ServletRequest request)
    Public ActionErrors validate(ActionMappin mapping, HttpServletRequest request)
    你應該在自己的bean里覆蓋validate()方法,并在配置文件里設置<action>元素的validate為true。在ActionServlet調用Action類前,它會調用validate(),如果返回的ActionErrors不是null,則Actinform會根據錯誤關鍵字將ActionErrors存儲在請求屬性列表中。
    如果返回的不是null,而且長度大于0,則根據錯誤關鍵字將實例存儲在請求的屬性列表中,然后ActionServlet將響應轉發到配置文件<action>元素的input屬性所指向的目標。
    如果需要執行特定的數據有效性檢查,最好在Action類中進行這個操作,而不是在Actionform類中進行。
    方法reset()可將bean的屬性恢復到默認值:
    public void reset(ActionMapping mapping,HttpServletRequest request)
    public void reset(ActionMapping mapping,ServletRequest request)
    典型的ActionFrom bean只有屬性的設置與讀取方法(getXXX),而沒有實現事務邏輯的方法。只有簡單的輸入檢查邏輯,使用的目的是為了存儲用戶在相關表單中輸入的最新數據,以便可以將同一網頁進行再生,同時提供一組錯誤信息,這樣就可以讓用戶修改不正確的輸入數據。而真正對數據有效性進行檢查的是Action類或適當的事務邏輯bean。
    Actionform中屬性允許的類型boolean,byte,short,char,int,long,float,double,Boolean,Btye,Short, Character,Integer,Long,Float,Double,String,Date,Time,Timestamp,Object,以及以上類型的數組。
    如果Actionform bean 的屬性是一個數組則相應的設置和讀取方法要做部分修改。對于數組setXXX(…),和getXXX()在jsp頁面中意義不大。應該將添加setXXX( int index , …. ) 方法和getXXX ( int index )方法。這兩個方法對于jsp頁面來說更有意義。jsp中的property應該是XXX[0]。
    如果Actionform bean的屬性是一個 Map則應該提供方法setXXX( String key , … )和getXXX(String key),使得jsp頁面可以訪問Map屬性。jsp中的properry應該是XXX(keyname)。
    通過getXXX(int index),setXXX (int index,…),getXXX(String key),setXXX(String key,…)可以方便的實現重復html輸入框。
    例如:
    public class Fooform extends Actionform {
    ? ?private String yourName;
    ? ?public String getYourName() {
    ? ? ? ?return yourName;
    ? ?}
    ? ?public void setYourName(String yourName) {
    ? ? ? ?this.yourName = yourName;
    ? ?}
    ? ?private final Map values = new HashMap();
    ? ?public void setvalue(String key, Object value) {
    ? ? ? ?values.put(key, value);
    ? ?}
    ? ?public Object getvalue(String key) {
    ? ? ? ?if ( values.containsKey(key)){
    ? ? ? ? ? ?return values.get(key);
    ? ? ? ?}else{
    ? ? ? ? ? ?return "";
    ? ? ? ?}
    ? ?}
    ? ?…
    }


    Validatorform類
    org.apache.struts.validator.Validatorform類繼承了Actionform類。使用本類可以方便的實現表單參數的校驗。在校驗的時候,使用在struts-config.xml中action元素中的name屬性,確定要在validation.xml中取得校驗規則的依據。
    使用本類可以方便的解決同一個form在不同的Action中使用不同的校驗規則的問題。在繼承了Validatorform的類中不再需要我們去寫validate方法。而是由Validatorform中的validate方法通過讀取validation.xml中的描述信息來進行數據的校驗。使用Validatorform也可以方便的實現在瀏覽器端實現利用腳本的校驗。
    Validatorform中的新增加的方法:
    int getPage()
    java.util.Map getResultvalueMap()
    ValidatorResults getValidatorResults()
    void setPage(int page)
    void setValidatorResults()
    使用本類可以大大提高我們的編程效率。
    ValidatorActionform類
    org.apache.struts.validator.ValidatorActionform類繼承了Validatorform類。使用本類可以方便的實現表單參數的校驗。在校驗的時候,使用在struts-config.xml中action元素中的path屬性,確定要在validation.xml中取得校驗規則的依據。

    DynaActionform類
    org.apache.struts.action.DynaActionform類繼承了Actionform類。使用本類可以方便的實現動態表單。創建不確定的表單,如果jsp發生了變化只需要修改jsp頁面和struts-config.xml文件中的form-bean元素就可以了。我們的程序中完全可以不用手工書寫actionform的類了。
    DynaActionform中的方法:
    boolean contains(String name, String key) 檢測name(key)在actionform中是否存在。
    Object get(String name) 從actionform中取得name的值。
    Object get(String name,int index) 從actionform中取得 name對象的index個值。
    Object get(String name,String key)從actionform中取得name對象的key對應的值。
    Map getMap() 返回對象中包含的對象屬性名列表。
    void remove(String name, String key) 刪除一個元素。
    void set(String name, int index,Object value) 對actionform中的屬性進行賦值。
    void set(String name,Object value)
    void set(String name, Strign key ,Object value)

    DynaValidatorform類
    org.apache.struts.validator.DynaValidatorform類繼承了DynaActionform類。使用本類可以方便的實現表單參數的校驗。在校驗的時候,使用在struts-config.xml中action元素中的name屬性,確定要在validation.xml中取得校驗規則的依據。
    至于校驗,同Validatorform。
    DynaValidatorform中的新增加的方法:
    int getPage()
    java.util.Map getResultvalueMap()
    ValidatorResults getValidatorResults()
    void setPage(int page)
    void setValidatorResults()

    DynaValidatorActionform類
    org.apache.struts.validator.DynaValidatorActionform類繼承了DynaValidatorform類。使用本類可以方便的實現表單參數的校驗。在校驗的時候,使用在struts-config.xml中action元素中的path屬性,確定要在validation.xml中取得校驗規則的依據。
    至于校驗,同Validatorform。

    ActionForward類
    ActionForward類繼承了org.apache.struts.config.ForwardConfig。
    ForwardConfig的方法:
    String getName() 虛名字
    String getPath() 實際路徑
    boolean getRedirect() 是否重定向
    void setName(String name)
    void setPath(String path)
    void setRedirect(boolean redirect)

    ActionForward目的是控制器將Action類的處理結果轉發至目的地。
    Action類獲得ActionForward實例的句柄,然后可用兩種方法返回到ActionServlet,
    ActionMapping實例被傳送到execute()方法,使用actionMapping的findForward(String name)根據名稱獲取一個全局轉發或本地轉發。
    另一種是調用下面的一個構造器來創建它們自己的一個實例:
    public ActionForward()
    public ActionForward(String path)
    public ActionForward(String path,Boolean redirect)
    public ActionForward(String name,String path,Boolean redirect)
    public ActionForward(String name,String path,Boolean redirect, boolean contextRelative)
    或下面的構造方法(下面是ActionForward的子類)
    ForwardingActionForward()
    ForwardingActionForward(String path) ?
    RedirectingActionForward()
    RedirectingActionForward(String path

    posted @ 2006-06-02 18:14 MyJavaWorld 閱讀(827) | 評論 (2)編輯 收藏

    1 定義頭和根元素

    部署描述符文件就像所有XML文件一樣,必須以一個XML頭開始。這個頭聲明可以使用的XML版本并給出文件的字符編碼。
    DOCYTPE聲明必須立即出現在此頭之后。這個聲明告訴服務器適用的servlet規范的版本(如2.2或2.3)并指定管理此文件其余部分內容的語法的DTD(Document Type Definition,文檔類型定義)。
    所有部署描述符文件的頂層(根)元素為web-app。請注意,XML元素不像HTML,他們是大小寫敏感的。因此,web-App和WEB-APP都是不合法的,web-app必須用小寫。

    2 部署描述符文件內的元素次序

    XML 元素不僅是大小寫敏感的,而且它們還對出現在其他元素中的次序敏感。例如,XML頭必須是文件中的第一項,DOCTYPE聲明必須是第二項,而web- app元素必須是第三項。在web-app元素內,元素的次序也很重要。服務器不一定強制要求這種次序,但它們允許(實際上有些服務器就是這樣做的)完全拒絕執行含有次序不正確的元素的Web應用。這表示使用非標準元素次序的web.xml文件是不可移植的。
    下面的列表給出了所有可直接出現在web-app元素內的合法元素所必需的次序。例如,此列表說明servlet元素必須出現在所有servlet-mapping元素之前。請注意,所有這些元素都是可選的。因此,可以省略掉某一元素,但不能把它放于不正確的位置。
    l icon icon元素指出IDE和GUI工具用來表示Web應用的一個和兩個圖像文件的位置。
    l display-name display-name元素提供GUI工具可能會用來標記這個特定的Web應用的一個名稱。
    l description description元素給出與此有關的說明性文本。
    l context-param context-param元素聲明應用范圍內的初始化參數。
    l filter 過濾器元素將一個名字與一個實現javax.servlet.Filter接口的類相關聯。
    l filter-mapping 一旦命名了一個過濾器,就要利用filter-mapping元素把它與一個或多個servlet或JSP頁面相關聯。
    l listener servlet API的版本2.3增加了對事件監聽程序的支持,事件監聽程序在建立、修改和刪除會話或servlet環境時得到通知。Listener元素指出事件監聽程序類。
    l servlet 在向servlet或JSP頁面制定初始化參數或定制URL時,必須首先命名servlet或JSP頁面。Servlet元素就是用來完成此項任務的。
    l servlet-mapping 服務器一般為servlet提供一個缺省的URL:http://host/webAppPrefix/servlet/ServletName。但是,常常會更改這個URL,以便servlet可以訪問初始化參數或更容易地處理相對URL。在更改缺省URL時,使用servlet-mapping元素。
    l session-config 如果某個會話在一定時間內未被訪問,服務器可以拋棄它以節省內存。可通過使用HttpSession的setMaxInactiveInterval方法明確設置單個會話對象的超時值,或者可利用session-config元素制定缺省超時值。
    l mime-mapping 如果Web應用具有想到特殊的文件,希望能保證給他們分配特定的MIME類型,則mime-mapping元素提供這種保證。
    l welcom-file-list welcome-file-list元素指示服務器在收到引用一個目錄名而不是文件名的URL時,使用哪個文件。
    l error-page error-page元素使得在返回特定HTTP狀態代碼時,或者特定類型的異常被拋出時,能夠制定將要顯示的頁面。
    l taglib taglib元素對標記庫描述符文件(Tag Libraryu Descriptor file)指定別名。此功能使你能夠更改TLD文件的位置,而不用編輯使用這些文件的JSP頁面。
    l resource-env-ref resource-env-ref元素聲明與資源相關的一個管理對象。
    l resource-ref resource-ref元素聲明一個資源工廠使用的外部資源。
    l security-constraint security-constraint元素制定應該保護的URL。它與login-config元素聯合使用
    l login-config 用login-config元素來指定服務器應該怎樣給試圖訪問受保護頁面的用戶授權。它與sercurity-constraint元素聯合使用。
    l security-role security-role元素給出安全角色的一個列表,這些角色將出現在servlet元素內的security-role-ref元素的role-name子元素中。分別地聲明角色可使高級IDE處理安全信息更為容易。
    l env-entry env-entry元素聲明Web應用的環境項。
    l ejb-ref ejb-ref元素聲明一個EJB的主目錄的引用。
    l ejb-local-ref ejb-local-ref元素聲明一個EJB的本地主目錄的應用。

    3 分配名稱和定制的UL

    在web.xml中完成的一個最常見的任務是對servlet或JSP頁面給出名稱和定制的URL。用servlet元素分配名稱,使用servlet-mapping元素將定制的URL與剛分配的名稱相關聯。
    3.1 分配名稱
    為了提供初始化參數,對servlet或JSP頁面定義一個定制URL或分配一個安全角色,必須首先給servlet或JSP頁面一個名稱。可通過 servlet元素分配一個名稱。最常見的格式包括servlet-name和servlet-class子元素(在web-app元素內),如下所示:

    <servlet>
    <servlet-name>Test</servlet-name>
    <servlet-class>moreservlets.TestServlet</servlet-class>
    </servlet>

    這表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已經得到了注冊名Test。給 servlet一個名稱具有兩個主要的含義。首先,初始化參數、定制的URL模式以及其他定制通過此注冊名而不是類名引用此servlet。其次,可在 URL而不是類名中使用此名稱。因此,利用剛才給出的定義,URL http://host/webAppPrefix/servlet/Test 可用于 http://host/webAppPrefix/servlet/moreservlets.TestServlet 的場所。
    請記住:XML元素不僅是大小寫敏感的,而且定義它們的次序也很重要。例如,web-app元素內所有servlet元素必須位于所有servlet- mapping元素(下一小節介紹)之前,而且還要位于5.6節和5.11節討論的與過濾器或文檔相關的元素(如果有的話)之前。類似地,servlet 的servlet-name子元素也必須出現在servlet-class之前。5.2節”部署描述符文件內的元素次序”將詳細介紹這種必需的次序。
    例如,程序清單5-1給出了一個名為TestServlet的簡單servlet,它駐留在moreservlets程序包中。因為此servlet是扎根在一個名為deployDemo的目錄中的Web應用的組成部分,所以TestServlet.class放在deployDemo/WEB- INF/classes/moreservlets中。程序清單5-2給出將放置在deployDemo/WEB-INF/內的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素將名稱Test與TestServlet.class相關聯。圖 5-1和圖5-2分別顯示利用缺省URL和注冊名調用TestServlet時的結果。

    程序清單5-1 TestServlet.java
    package moreservlets;

    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    /** Simple servlet used to illustrate servlet naming
    * and custom URLs.
    * <P>
    * Taken from More Servlets and JavaServer Pages
    * from Prentice Hall and Sun Microsystems Press,
    * http://www.moreservlets.com/.
    * ? 2002 Marty Hall; may be freely used or adapted.
    */
    
    public class TestServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String uri = request.getRequestURI();
    out.println(ServletUtilities.headWithTitle("Test Servlet") +
    "<BODY BGCOLOR=\"#FDF5E6\">\n" +
    "<H2>URI: " + uri + "</H2>\n" +
    "</BODY></HTML>");
    }
    }

    程序清單5-2 web.xml(說明servlet名稱的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- … -->
    <servlet>
    <servlet-name>Test</servlet-name>
    <servlet-class>moreservlets.TestServlet</servlet-class>
    </servlet>
    <!-- … -->
    </web-app>

    3.2 定義定制的URL
    大多數服務器具有一個缺省的serlvet URL:
    http://host/webAppPrefix/servlet/packageName.ServletName。雖然在開發中使用這個URL很方便,但是我們常常會希望另一個URL用于部署。例如,可能會需要一個出現在Web應用頂層的URL(如,http: //host/webAppPrefix/Anyname),并且在此URL中沒有servlet項。位于頂層的URL簡化了相對URL的使用。此外,對許多開發人員來說,頂層URL看上去比更長更麻煩的缺省URL更簡短。
    事實上,有時需要使用定制的URL。比如,你可能想關閉缺省URL映射,以便更好地強制實施安全限制或防止用戶意外地訪問無初始化參數的servlet。如果你禁止了缺省的URL,那么你怎樣訪問servlet呢?這時只有使用定制的URL了。
    為了分配一個定制的URL,可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一個任意名稱,可利用此名稱引用相應的servlet;url-pattern描述了相對于Web應用的根目錄的URL。url- pattern元素的值必須以斜杠(/)起始。
    下面給出一個簡單的web.xml摘錄,它允許使用URL http://host/webAppPrefix/UrlTest而不是http://host/webAppPrefix/servlet/Test或
    http: //host/webAppPrefix/servlet/moreservlets.TestServlet。請注意,仍然需要XML頭、 DOCTYPE聲明以及web-app封閉元素。此外,可回憶一下,XML元素出現地次序不是隨意的。特別是,需要把所有servlet元素放在所有 servlet-mapping元素之前。

    <servlet>
    <servlet-name>Test</servlet-name>
    <servlet-class>moreservlets.TestServlet</servlet-class>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name>Test</servlet-name>
    <url-pattern>/UrlTest</url-pattern>
    </servlet-mapping>

    URL模式還可以包含通配符。例如,下面的小程序指示服務器發送所有以Web應用的URL前綴開始,以..asp結束的請求到名為BashMS的servlet。

    <servlet>
    <servlet-name>BashMS</servlet-name>
    <servlet-class>msUtils.ASPTranslator</servlet-class>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name>BashMS</servlet-name>
    <url-pattern>/*.asp</url-pattern>
    </servlet-mapping>

    3.3 命名JSP頁面
    因為JSP頁面要轉換成sevlet,自然希望就像命名servlet一樣命名JSP頁面。畢竟,JSP頁面可能會從初始化參數、安全設置或定制的URL中受益,正如普通的serlvet那樣。雖然JSP頁面的后臺實際上是servlet這句話是正確的,但存在一個關鍵的猜疑:即,你不知道JSP頁面的實際類名(因為系統自己挑選這個名字)。因此,為了命名JSP頁面,可將jsp-file元素替換為servlet-calss元素,如下所示:

    <servlet>
    <servlet-name>Test</servlet-name>
    <jsp-file>/TestPage.jsp</jsp-file>
    </servlet>

    命名JSP頁面的原因與命名servlet的原因完全相同:即為了提供一個與定制設置(如,初始化參數和安全設置)一起使用的名稱,并且,以便能更改激活 JSP頁面的URL(比方說,以便多個URL通過相同頁面得以處理,或者從URL中去掉.jsp擴展名)。但是,在設置初始化參數時,應該注意,JSP頁面是利用jspInit方法,而不是init方法讀取初始化參數的。
    例如,程序清單5-3給出一個名為TestPage.jsp的簡單JSP頁面,它的工作只是打印出用來激活它的URL的本地部分。TestPage.jsp放置在deployDemo應用的頂層。程序清單5-4給出了用來分配一個注冊名PageName,然后將此注冊名與http://host/webAppPrefix/UrlTest2/anything 形式的URL相關聯的web.xml文件(即,deployDemo/WEB-INF/web.xml)的一部分。

    程序清單5-3 TestPage.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE>
    JSP Test Page
    </TITLE>
    </HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <H2>URI: <%= request.getRequestURI() %></H2>
    </BODY>
    </HTML>

    程序清單5-4 web.xml(說明JSP頁命名的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <servlet>
    <servlet-name>PageName</servlet-name>
    <jsp-file>/TestPage.jsp</jsp-file>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name> PageName </servlet-name>
    <url-pattern>/UrlTest2/*</url-pattern>
    </servlet-mapping>
    <!-- ... -->
    </web-app>

    4 禁止激活器servlet

    對servlet 或JSP頁面建立定制URL的一個原因是,這樣做可以注冊從 init(servlet)或jspInit(JSP頁面)方法中讀取得初始化參數。但是,初始化參數只在是利用定制URL模式或注冊名訪問 servlet或JSP頁面時可以使用,用缺省URL http://host/webAppPrefix/servlet/ServletName 訪問時不能使用。因此,你可能會希望關閉缺省URL,這樣就不會有人意外地調用初始化servlet了。這個過程有時稱為禁止激活器servlet,因為多數服務器具有一個用缺省的servlet URL注冊的標準servlet,并激活缺省的URL應用的實際servlet。
    有兩種禁止此缺省URL的主要方法:
    l 在每個Web應用中重新映射/servlet/模式。
    l 全局關閉激活器servlet。
    重要的是應該注意到,雖然重新映射每個Web應用中的/servlet/模式比徹底禁止激活servlet所做的工作更多,但重新映射可以用一種完全可移植的方式來完成。相反,全局禁止激活器servlet完全是針對具體機器的,事實上有的服務器(如ServletExec)沒有這樣的選擇。下面的討論對每個Web應用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的詳細內容。
    4.1 重新映射/servlet/URL模式
    在一個特定的Web應用中禁止以http://host/webAppPrefix/servlet/ 開始的URL的處理非常簡單。所需做的事情就是建立一個錯誤消息servlet,并使用前一節討論的url-pattern元素將所有匹配請求轉向該 servlet。只要簡單地使用:

    <url-pattern>/servlet/*</url-pattern>

    作為servlet-mapping元素中的模式即可。
    例如,程序清單5-5給出了將SorryServlet servlet(程序清單5-6)與所有以http://host/webAppPrefix/servlet/ 開頭的URL相關聯的部署描述符文件的一部分。

    程序清單5-5 web.xml(說明JSP頁命名的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <servlet>
    <servlet-name>Sorry</servlet-name>
    <servlet-class>moreservlets.SorryServlet</servlet-class>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name> Sorry </servlet-name>
    <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    <!-- ... -->
    </web-app>

    程序清單5-6 SorryServlet.java

    package moreservlets;
    
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    
    /** Simple servlet used to give error messages to
    * users who try to access default servlet URLs
    * (i.e., http://host/webAppPrefix/servlet/ServletName)
    * in Web applications that have disabled this
    * behavior.
    * <P>
    * Taken from More Servlets and JavaServer Pages
    * from Prentice Hall and Sun Microsystems Press,
    * http://www.moreservlets.com/.
    * ? 2002 Marty Hall; may be freely used or adapted.
    */
    
    public class SorryServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String title = "Invoker Servlet Disabled.";
    out.println(ServletUtilities.headWithTitle(title) +
    "<BODY BGCOLOR=\"#FDF5E6\">\n" +
    "<H2>" + title + "</H2>\n" +
    "Sorry, access to servlets by means of\n" +
    "URLs that begin with\n" +
    "http://host/webAppPrefix/servlet/\n" +
    "has been disabled.\n" +
    "</BODY></HTML>");
    }
    
    public void doPost(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    doGet(request, response);
    }
    }

    4.2 全局禁止激活器:Tomcat
    Tomcat 4中用來關閉缺省URL的方法與Tomcat 3中所用的很不相同。下面介紹這兩種方法:
    1.禁止激活器: Tomcat 4
    Tomcat 4用與前面相同的方法關閉激活器servlet,即利用web.xml中的url-mapping元素進行關閉。不同之處在于Tomcat使用了放在 install_dir/conf中的一個服務器專用的全局web.xml文件,而前面使用的是存放在每個Web應用的WEB-INF目錄中的標準 web.xml文件。
    因此,為了在Tomcat 4中關閉激活器servlet,只需在install_dir/conf/web.xml中簡單地注釋出/servlet/* URL映射項即可,如下所示:

    <!--
    <servlet-mapping>
    <servlet-name>invoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    -->

    再次提醒,應該注意這個項是位于存放在install_dir/conf的Tomcat專用的web.xml文件中的,此文件不是存放在每個Web應用的WEB-INF目錄中的標準web.xml。
    2.禁止激活器:Tomcat3
    在Apache Tomcat的版本3中,通過在install_dir/conf/server.xml中注釋出InvokerInterceptor項全局禁止缺省 servlet URL。例如,下面是禁止使用缺省servlet URL的server.xml文件的一部分。

    <!--
    <RequsetInterceptor
    className="org.apache.tomcat.request.InvokerInterceptor"
    debug="0" prefix="/servlet/" />
    -->

    5 初始化和預裝載servlet與JSP頁面

    這里討論控制servlet和JSP頁面的啟動行為的方法。特別是,說明了怎樣分配初始化參數以及怎樣更改服務器生存期中裝載servlet和JSP頁面的時刻。
    5.1 分配servlet初始化參數
    利用init-param元素向servlet提供初始化參數,init-param元素具有param-name和param-value子元素。例如,在下面的例子中,如果initServlet servlet是利用它的注冊名(InitTest)訪問的,它將能夠從其方法中調用getServletConfig(). getInitParameter(”param1″)獲得”Value 1″,調用getServletConfig().getInitParameter(”param2″)獲得”2″。

    <servlet>
    <servlet-name>InitTest</servlet-name>
    <servlet-class>moreservlets.InitServlet</servlet-class>
    <init-param>
    <param-name>param1</param-name>
    <param-value>value1</param-value>
    </init-param>
    <init-param>
    <param-name>param2</param-name>
    <param-value>2</param-value>
    </init-param>
    </servlet>

    在涉及初始化參數時,有幾點需要注意:
    l 返回值。GetInitParameter的返回值總是一個String。因此,在前一個例子中,可對param2使用Integer.parseInt獲得一個int。
    l JSP中的初始化。JSP頁面使用jspInit而不是init。JSP頁面還需要使用jsp-file元素代替servlet-class。
    l 缺省URL。初始化參數只在通過它們的注冊名或與它們注冊名相關的定制URL模式訪問Servlet時可以使用。因此,在這個例子中,param1和 param2初始化參數將能夠在使用URL http://host/webAppPrefix/servlet/InitTest 時可用,但在使用URL http://host/webAppPrefix/servlet/myPackage.InitServlet 時不能使用。
    例如,程序清單5-7給出一個名為InitServlet的簡單servlet,它使用init方法設置firstName和emailAddress字段。程序清單5-8給出分配名稱InitTest給servlet的web.xml文件。
    程序清單5-7 InitServlet.java

    package moreservlets;
    
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    
    /** Simple servlet used to illustrate servlet
    * initialization parameters.
    * <P>
    * Taken from More Servlets and JavaServer Pages
    * from Prentice Hall and Sun Microsystems Press,
    * http://www.moreservlets.com/.
    * ? 2002 Marty Hall; may be freely used or adapted.
    */
    
    public class InitServlet extends HttpServlet {
    private String firstName, emailAddress;
    
    public void init() {
    ServletConfig config = getServletConfig();
    firstName = config.getInitParameter("firstName");
    emailAddress = config.getInitParameter("emailAddress");
    }
    
    public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String uri = request.getRequestURI();
    out.println(ServletUtilities.headWithTitle("Init Servlet") +
    "<BODY BGCOLOR=\"#FDF5E6\">\n" +
    "<H2>Init Parameters:</H2>\n" +
    "<UL>\n" +
    "<LI>First name: " + firstName + "\n" +
    "<LI>Email address: " + emailAddress + "\n" +
    "</UL>\n" +
    "</BODY></HTML>");
    }
    }

    程序清單5-8 web.xml(說明初始化參數的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <servlet>
    <servlet-name>InitTest</servlet-name>
    <servlet-class>moreservlets.InitServlet</servlet-class>
    <init-param>
    <param-name>firstName</param-name>
    <param-value>Larry</param-value>
    </init-param>
    <init-param>
    <param-name>emailAddress</param-name>
    <param-value>Ellison@Microsoft.com</param-value>
    </init-param>
    </servlet>
    <!-- ... -->
    </web-app>

    5.2 分配JSP初始化參數
    給JSP頁面提供初始化參數在三個方面不同于給servlet提供初始化參數。
    1)使用jsp-file而不是servlet-class。因此,WEB-INF/web.xml文件的servlet元素如下所示:

    <servlet>
    <servlet-name>PageName</servlet-name>
    <jsp-file>/RealPage.jsp</jsp-file>
    <init-param>
    <param-name>...</param-name>
    <param-value>...</param-value>
    </init-param>
    ...
    </servlet>

    2) 幾乎總是分配一個明確的URL模式。對servlet,一般相應地使用以http://host/webAppPrefix/servlet/ 開始的缺省URL。只需記住,使用注冊名而不是原名稱即可。這對于JSP頁面在技術上也是合法的。例如,在上面給出的例子中,可用URL http://host/webAppPrefix/servlet/PageName 訪問RealPage.jsp的對初始化參數具有訪問權的版本。但在用于JSP頁面時,許多用戶似乎不喜歡應用常規的servlet的URL。此外,如果 JSP頁面位于服務器為其提供了目錄清單的目錄中(如,一個既沒有index.html也沒有index.jsp文件的目錄),則用戶可能會連接到此 JSP頁面,單擊它,從而意外地激活未初始化的頁面。因此,好的辦法是使用url-pattern(5.3節)將JSP頁面的原URL與注冊的 servlet名相關聯。這樣,客戶機可使用JSP頁面的普通名稱,但仍然激活定制的版本。例如,給定來自項目1的servlet定義,可使用下面的 servlet-mapping定義:

    <servlet-mapping>
    <servlet-name>PageName</servlet-name>
    <url-pattern>/RealPage.jsp</url-pattern>
    </servlet-mapping>

    3)JSP頁使用jspInit而不是init。自動從JSP頁面建立的servlet或許已經使用了inti方法。因此,使用JSP聲明提供一個init方法是不合法的,必須制定jspInit方法。
    為了說明初始化JSP頁面的過程,程序清單5-9給出了一個名為InitPage.jsp的JSP頁面,它包含一個jspInit方法且放置于 deployDemo Web應用層次結構的頂層。一般,http://host/deployDemo/InitPage.jsp 形式的URL將激活此頁面的不具有初始化參數訪問權的版本,從而將對firstName和emailAddress變量顯示null。但是, web.xml文件(程序清單5-10)分配了一個注冊名,然后將該注冊名與URL模式/InitPage.jsp相關聯。

    程序清單5-9 InitPage.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD><TITLE>JSP Init Test</TITLE></HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <H2>Init Parameters:</H2>
    <UL>
    <LI>First name: <%= firstName %>
    <LI>Email address: <%= emailAddress %>
    </UL>
    </BODY></HTML>
    <%!
    private String firstName, emailAddress;
    
    public void jspInit() {
    ServletConfig config = getServletConfig();
    firstName = config.getInitParameter("firstName");
    emailAddress = config.getInitParameter("emailAddress");
    }
    %>

    程序清單5-10 web.xml(說明JSP頁面的init參數的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <servlet>
    <servlet-name>InitPage</servlet-name>
    <jsp-file>/InitPage.jsp</jsp-file>
    <init-param>
    <param-name>firstName</param-name>
    <param-value>Bill</param-value>
    </init-param>
    <init-param>
    <param-name>emailAddress</param-name>
    <param-value>gates@oracle.com</param-value>
    </init-param>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name> InitPage</servlet-name>
    <url-pattern>/InitPage.jsp</url-pattern>
    </servlet-mapping>
    <!-- ... -->
    </web-app>

    5.3 提供應用范圍內的初始化參數
    一般,對單個地servlet或JSP頁面分配初始化參數。指定的servlet或JSP頁面利用ServletConfig的 getInitParameter方法讀取這些參數。但是,在某些情形下,希望提供可由任意servlet或JSP頁面借助ServletContext 的getInitParameter方法讀取的系統范圍內的初始化參數。
    可利用context-param元素聲明這些系統范圍內的初始化值。context-param元素應該包含param-name、param-value以及可選的description子元素,如下所示:

    <context-param>
    <param-name>support-email</param-name>
    <param-value>blackhole@mycompany.com</param-value>
    </context-param>

    可回憶一下,為了保證可移植性,web.xml內的元素必須以正確的次序聲明。但這里應該注意,context-param元素必須出現任意與文檔有關的元素(icon、display-name或description)之后及filter、filter-mapping、listener或 servlet元素之前。
    5.4 在服務器啟動時裝載servlet
    假如servlet或JSP頁面有一個要花很長時間執行的init (servlet)或jspInit(JSP)方法。例如,假如init或jspInit方法從某個數據庫或ResourceBundle查找產量。這種情況下,在第一個客戶機請求時裝載servlet的缺省行為將對第一個客戶機產生較長時間的延遲。因此,可利用servlet的load-on- startup元素規定服務器在第一次啟動時裝載servlet。下面是一個例子。

    <servlet>
    <servlet-name> … </servlet-name>
    <servlet-class> … </servlet-class> <!-- Or jsp-file -->
    <load-on-startup/>
    </servlet>

    可以為此元素體提供一個整數而不是使用一個空的load-on-startup。想法是服務器應該在裝載較大數目的servlet或JSP頁面之前裝載較少數目的servlet或JSP頁面。例如,下面的servlet項(放置在Web應用的WEB-INF目錄下的web.xml文件中的web-app元素內)將指示服務器首先裝載和初始化SearchServlet,然后裝載和初始化由位于Web應用的result目錄中的index.jsp文件產生的 servlet。

    <servlet>
    <servlet-name>Search</servlet-name>
    <servlet-class>myPackage.SearchServlet</servlet-class> <!-- Or jsp-file -->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
    <servlet-name>Results</servlet-name>
    <servlet-class>/results/index.jsp</servlet-class> <!-- Or jsp-file -->
    <load-on-startup>2</load-on-startup>
    </servlet>

    6 聲明過濾器

    servlet版本2.3引入了過濾器的概念。雖然所有支持servlet API版本2.3的服務器都支持過濾器,但為了使用與過濾器有關的元素,必須在web.xml中使用版本2.3的DTD。
    過濾器可截取和修改進入一個servlet或JSP頁面的請求或從一個servlet或JSP頁面發出的相應。在執行一個servlet或JSP頁面之前,必須執行第一個相關的過濾器的doFilter方法。在該過濾器對其FilterChain對象調用doFilter時,執行鏈中的下一個過濾器。如果沒有其他過濾器,servlet或JSP頁面被執行。過濾器具有對到來的ServletRequest對象的全部訪問權,因此,它們可以查看客戶機名、查找到來的cookie等。為了訪問servlet或JSP頁面的輸出,過濾器可將響應對象包裹在一個替身對象(stand-in object)中,比方說把輸出累加到一個緩沖區。在調用FilterChain對象的doFilter方法之后,過濾器可檢查緩沖區,如有必要,就對它進行修改,然后傳送到客戶機。
    例如,程序清單5-11帝國難以了一個簡單的過濾器,只要訪問相關的servlet或JSP頁面,它就截取請求并在標準輸出上打印一個報告(開發過程中在桌面系統上運行時,大多數服務器都可以使用這個過濾器)。

    程序清單5-11 ReportFilter.java

    package moreservlets;
    
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.util.*;
    
    /** Simple filter that prints a report on the standard output
    * whenever the associated servlet or JSP page is accessed.
    * <P>
    * Taken from More Servlets and JavaServer Pages
    * from Prentice Hall and Sun Microsystems Press,
    * http://www.moreservlets.com/.
    * ? 2002 Marty Hall; may be freely used or adapted.
    */
    
    public class ReportFilter implements Filter {
    public void doFilter(ServletRequest request,
    ServletResponse response,
    FilterChain chain)
    throws ServletException, IOException {
    HttpServletRequest req = (HttpServletRequest)request;
    System.out.println(req.getRemoteHost() +
    " tried to access " +
    req.getRequestURL() +
    " on " + new Date() + ".");
    chain.doFilter(request,response);
    }
    
    public void init(FilterConfig config)
    throws ServletException {
    }
    
    public void destroy() {}
    }

    一旦建立了一個過濾器,可以在web.xml中利用filter元素以及filter-name(任意名稱)、file-class(完全限定的類名)和(可選的)init-params子元素聲明它。請注意,元素在web.xml的web-app元素中出現的次序不是任意的;允許服務器(但不是必需的)強制所需的次序,并且實際中有些服務器也是這樣做的。但這里要注意,所有filter元素必須出現在任意filter-mapping元素之前, filter-mapping元素又必須出現在所有servlet或servlet-mapping元素之前。
    例如,給定上述的ReportFilter類,可在web.xml中作出下面的filter聲明。它把名稱Reporter與實際的類ReportFilter(位于moreservlets程序包中)相關聯。

    <filter>
    <filter-name>Reporter</filter-name>
    <filter-class>moresevlets.ReportFilter</filter-class>
    </filter>

    一旦命名了一個過濾器,可利用filter-mapping元素把它與一個或多個servlet或JSP頁面相關聯。關于此項工作有兩種選擇。
    首先,可使用filter-name和servlet-name子元素把此過濾器與一個特定的servlet名(此servlet名必須稍后在相同的 web.xml文件中使用servlet元素聲明)關聯。例如,下面的程序片斷指示系統只要利用一個定制的URL訪問名為SomeServletName 的servlet或JSP頁面,就運行名為Reporter的過濾器。

    <filter-mapping>
    <filter-name>Reporter</filter-name>
    <servlet-name>SomeServletName</servlet-name>
    </filter-mapping>

    其次,可利用filter-name和url-pattern子元素將過濾器與一組servlet、JSP頁面或靜態內容相關聯。例如,相面的程序片段指示系統只要訪問Web應用中的任意URL,就運行名為Reporter的過濾器。

    <filter-mapping>
    <filter-name>Reporter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    例如,程序清單5-12給出了將ReportFilter過濾器與名為PageName的servlet相關聯的web.xml文件的一部分。名字 PageName依次又與一個名為TestPage.jsp的JSP頁面以及以模式http: //host/webAppPrefix/UrlTest2/ 開頭的URL相關聯。TestPage.jsp的源代碼已經JSP頁面命名的談論在前面的3節”分配名稱和定制的URL”中給出。事實上,程序清單5- 12中的servlet和servlet-name項從該節原封不動地拿過來的。給定這些web.xml項,可看到下面的標準輸出形式的調試報告(換行是為了容易閱讀)。
    audit.irs.gov tried to access
    mycompany.com/deployDemo/UrlTest2/business/tax-plan.html
    on Tue Dec 25 13:12:29 EDT 2001.

    程序清單5-12 Web.xml(說明filter用法的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <filter>
    <filter-name>Reporter</filter-name>
    <filter-class>moresevlets.ReportFilter</filter-class>
    </filter>
    <!-- ... -->
    <filter-mapping>
    <filter-name>Reporter</filter-name>
    <servlet-name>PageName</servlet-name>
    </filter-mapping>
    <!-- ... -->
    <servlet>
    <servlet-name>PageName</servlet-name>
    <jsp-file>/RealPage.jsp</jsp-file>
    </servlet>
    <!-- ... -->
    <servlet-mapping>
    <servlet-name> PageName </servlet-name>
    <url-pattern>/UrlTest2/*</url-pattern>
    </servlet-mapping>
    <!-- ... -->
    </web-app>

    7 指定歡迎頁

    假如用戶提供了一個像http: //host/webAppPrefix/directoryName/ 這樣的包含一個目錄名但沒有包含文件名的URL,會發生什么事情呢?用戶能得到一個目錄表?一個錯誤?還是標準文件的內容?如果得到標準文件內容,是 index.html、index.jsp、default.html、default.htm或別的什么東西呢?
    Welcome-file-list 元素及其輔助的welcome-file元素解決了這個模糊的問題。例如,下面的web.xml項指出,如果一個URL給出一個目錄名但未給出文件名,服務器應該首先試用index.jsp,然后再試用index.html。如果兩者都沒有找到,則結果有賴于所用的服務器(如一個目錄列表)。

    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    雖然許多服務器缺省遵循這種行為,但不一定必須這樣。因此,明確地使用welcom-file-list保證可移植性是一種良好的習慣。

    8 指定處理錯誤的頁面

    現在我了解到,你在開發servlet和JSP頁面時從不會犯錯誤,而且你的所有頁面是那樣的清晰,一般的程序員都不會被它們的搞糊涂。但是,是人總會犯錯誤的,用戶可能會提供不合規定的參數,使用不正確的URL或者不能提供必需的表單字段值。除此之外,其它開發人員可能不那么細心,他們應該有些工具來克服自己的不足。
    error-page元素就是用來克服這些問題的。它有兩個可能的子元素,分別是:error-code和exception- type。第一個子元素error-code指出在給定的HTTP錯誤代碼出現時使用的URL。第二個子元素excpetion-type指出在出現某個給定的Java異常但未捕捉到時使用的URL。error-code和exception-type都利用location元素指出相應的URL。此 URL必須以/開始。location所指出的位置處的頁面可通過查找HttpServletRequest對象的兩個專門的屬性來訪問關于錯誤的信息,這兩個屬性分別是:javax.servlet.error.status_code和javax.servlet.error.message。
    可回憶一下,在web.xml內以正確的次序聲明web-app的子元素很重要。這里只要記住,error-page出現在web.xml文件的末尾附近,servlet、servlet-name和welcome-file-list之后即可。

    8.1 error-code元素
    為了更好地了解error-code元素的值,可考慮一下如果不正確地輸入文件名,大多數站點會作出什么反映。這樣做一般會出現一個404錯誤信息,它表示不能找到該文件,但幾乎沒提供更多有用的信息。另一方面,可以試一下在www.microsoft.com、www.ibm.com 處或者特別是在www.bea.com 處輸出未知的文件名。這是會得出有用的消息,這些消息提供可選擇的位置,以便查找感興趣的頁面。提供這樣有用的錯誤頁面對于Web應用來說是很有價值得。事實上rm-error-page子元素)。由form-login-page給出的HTML表單必須具有一個j_security_check的 ACTION屬性、一個名為j_username的用戶名文本字段以及一個名為j_password的口令字段。
    例如,程序清單5-19指示服務器使用基于表單的驗證。Web應用的頂層目錄中的一個名為login.jsp的頁面將收集用戶名和口令,并且失敗的登陸將由相同目錄中名為login-error.jsp的頁面報告。

    程序清單5-19 web.xml(說明login-config的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <security-constraint> ... </security-constraint>
    <login-config>
    <auth-method> FORM </auth-method>
    <form-login-config>
    <form-login-page>/login.jsp</form-login-page>
    <form-error-page>/login-error.jsp</form-error-page>
    </form-login-config>
    </login-config>
    <!-- ... -->
    </web-app>

    9.2 限制對Web資源的訪問
    現在,可以指示服務器使用何種驗證方法了。”了不起,”你說道,”除非我能指定一個來收到保護的 URL,否則沒有多大用處。”沒錯。指出這些URL并說明他們應該得到何種保護正是security-constriaint元素的用途。此元素在 web.xml中應該出現在login-config的緊前面。它包含是個可能的子元素,分別是:web-resource-collection、 auth-constraint、user-data-constraint和display-name。下面各小節對它們進行介紹。
    l web-resource-collection
    此元素確定應該保護的資源。所有security-constraint元素都必須包含至少一個web-resource-collection項。此元素由一個給出任意標識名稱的web-resource-name元素、一個確定應該保護的URL的url-pattern元素、一個指出此保護所適用的 HTTP命令(GET、POST等,缺省為所有方法)的http-method元素和一個提供資料的可選description元素組成。例如,下面的 Web-resource-collection項(在security-constratint元素內)指出Web應用的proprietary目錄中所有文檔應該受到保護。

    <security-constraint>
    <web-resource-coolection>
    <web-resource-name>Proprietary</web-resource-name>
    <url-pattern>/propritary/*</url-pattern>
    </web-resource-coolection>
    <!-- ... -->
    </security-constraint>

    重要的是應該注意到,url-pattern僅適用于直接訪問這些資源的客戶機。特別是,它不適合于通過MVC體系結構利用 RequestDispatcher來訪問的頁面,或者不適合于利用類似jsp:forward的手段來訪問的頁面。這種不勻稱如果利用得當的話很有好處。例如,servlet可利用MVC體系結構查找數據,把它放到bean中,發送請求到從bean中提取數據的JSP頁面并顯示它。我們希望保證決不直接訪問受保護的JSP頁面,而只是通過建立該頁面將使用的bean的servlet來訪問它。url-pattern和auth-contraint元素可通過聲明不允許任何用戶直接訪問JSP頁面來提供這種保證。但是,這種不勻稱的行為可能讓開發人員放松警惕,使他們偶然對應受保護的資源提供不受限制的訪問。
    l auth-constraint
    盡管web-resource-collention元素質出了哪些URL應該受到保護,但是auth-constraint元素卻指出哪些用戶應該具有受保護資源的訪問權。此元素應該包含一個或多個標識具有訪問權限的用戶類別role- name元素,以及包含(可選)一個描述角色的description元素。例如,下面web.xml中的security-constraint元素部門規定只有指定為Administrator或Big Kahuna(或兩者)的用戶具有指定資源的訪問權。

    <security-constraint>
    <web-resource-coolection> ... </web-resource-coolection>
    <auth-constraint>
    <role-name>administrator</role-name>
    <role-name>kahuna</role-name>
    </auth-constraint>
    </security-constraint>

    重要的是認識到,到此為止,這個過程的可移植部分結束了。服務器怎樣確定哪些用戶處于任何角色以及它怎樣存放用戶的口令,完全有賴于具體的系統。
    例如,Tomcat使用install_dir/conf/tomcat-users.xml將用戶名與角色名和口令相關聯,正如下面例子中所示,它指出用戶joe(口令bigshot)和jane(口令enaj)屬于administrator和kahuna角色。

    <tomcat-users>
    <user name="joe" password="bigshot" roles="administrator,kahuna" />
    <user name="jane" password="enaj" roles="kahuna" />
    </tomcat-users>

    l user-data-constraint
    這個可選的元素指出在訪問相關資源時使用任何傳輸層保護。它必須包含一個transport-guarantee子元素(合法值為NONE、 INTEGRAL或CONFIDENTIAL),并且可選地包含一個description元素。transport-guarantee為NONE值將對所用的通訊協議不加限制。INTEGRAL值表示數據必須以一種防止截取它的人閱讀它的方式傳送。雖然原理上(并且在未來的HTTP版本中),在 INTEGRAL和CONFIDENTIAL之間可能會有差別,但在當前實踐中,他們都只是簡單地要求用SSL。例如,下面指示服務器只允許對相關資源做 HTTPS連接:

    <security-constraint>
    <!-- ... -->
    <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
    </security-constraint>

    l display-name
    security-constraint的這個很少使用的子元素給予可能由GUI工具使用的安全約束項一個名稱。
    9.3 分配角色名
    迄今為止,討論已經集中到完全由容器(服務器)處理的安全問題之上了。但servlet以及JSP頁面也能夠處理它們自己的安全問題。
    例如,容器可能允許用戶從bigwig或bigcheese角色訪問一個顯示主管人員額外緊貼的頁面,但只允許bigwig用戶修改此頁面的參數。完成這種更細致的控制的一種常見方法是調用HttpServletRequset的isUserInRole方法,并據此修改訪問。
    Servlet的 security-role-ref子元素提供出現在服務器專用口令文件中的安全角色名的一個別名。例如,假如編寫了一個調用 request.isUserInRole(”boss”)的servlet,但后來該servlet被用在了一個其口令文件調用角色manager而不是boss的服務器中。下面的程序段使該servlet能夠使用這兩個名稱中的任何一個。

    <servlet>
    <!-- ... -->
    <security-role-ref>
    <role-name>boss</role-name> <!-- New alias -->
    <role-link>manager</role-link> <!-- Real name -->
    </security-role-ref>
    </servlet>

    也可以在web-app內利用security-role元素提供將出現在role-name元素中的所有安全角色的一個全局列表。分別地生命角色使高級IDE容易處理安全信息。

    10 控制會話超時

    如果某個會話在一定的時間內未被訪問,服務器可把它扔掉以節約內存。可利用HttpSession的setMaxInactiveInterval方法直接設置個別會話對象的超時值。如果不采用這種方法,則缺省的超時值由具體的服務器決定。但可利用session-config和session- timeout元素來給出一個適用于所有服務器的明確的超時值。超時值的單位為分鐘,因此,下面的例子設置缺省會話超時值為三個小時(180分鐘)。

    <session-config>
    <session-timeout>180</session-timeout>
    </session-config>

    11 Web應用的文檔化

    越來越多的開發環境開始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio(寫此文時,已被Macromedia收購)以及IBM VisuaAge for Java等。
    大量的web.xml元素不僅是為服務器設計的,而且還是為可視開發環境設計的。它們包括icon、display-name和discription等。
    可回憶一下,在web.xml內以適當地次序聲明web-app子元素很重要。不過,這里只要記住icon、display-name和description是web.xml的web-app元素內的前三個合法元素即可。
    l icon
    icon元素指出GUI工具可用來代表Web應用的一個和兩個圖像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG圖像,用large-icon元素指定一幅32 x 32的圖像。下面舉一個例子:

    <icon>
    <small-icon>/images/small-book.gif</small-icon>
    <large-icon>/images/tome.jpg</large-icon>
    </icon>

    l display-name
    display-name元素提供GUI工具可能會用來標記此Web應用的一個名稱。下面是個例子。

    <display-name>Rare Books</display-name>

    l description
    description元素提供解釋性文本,如下所示:

    <description>
    This Web application represents the store developed for
    rare-books.com, an online bookstore specializing in rare
    and limited-edition books.
    </description>

    12 關聯文件與MIME類型

    服務器一般都具有一種讓Web站點管理員將文件擴展名與媒體相關聯的方法。例如,將會自動給予名為mom.jpg的文件一個image/jpeg的MIME 類型。但是,假如你的Web應用具有幾個不尋常的文件,你希望保證它們在發送到客戶機時分配為某種MIME類型。mime-mapping元素(具有 extension和mime-type子元素)可提供這種保證。例如,下面的代碼指示服務器將application/x-fubar的MIME類型分配給所有以.foo結尾的文件。

    <mime-mapping>
    <extension>foo</extension>
    <mime-type>application/x-fubar</mime-type>
    </mime-mapping>

    或許,你的Web應用希望重載(override)標準的映射。例如,下面的代碼將告訴服務器在發送到客戶機時指定.ps文件作為純文本(text/plain)而不是作為PostScript(application/postscript)。

    <mime-mapping>
    <extension>ps</extension>
    <mime-type>application/postscript</mime-type>
    </mime-mapping>

    13 定位TLD

    JSP taglib元素具有一個必要的uri屬性,它給出一個TLD(Tag Library Descriptor)文件相對于Web應用的根的位置。TLD文件的實際名稱在發布新的標簽庫版本時可能會改變,但我們希望避免更改所有現有JSP頁面。此外,可能還希望使用保持taglib元素的簡練性的一個簡短的uri。這就是部署描述符文件的taglib元素派用場的所在了。Taglib包含兩個子元素:taglib-uri和taglib-location。taglib-uri元素應該與用于JSP taglib元素的uri屬性的東西相匹配。Taglib-location元素給出TLD文件的實際位置。例如,假如你將文件chart-tags- 1.3beta.tld放在WebApp/WEB-INF/tlds中。現在,假如web.xml在web-app元素內包含下列內容。

    <taglib>
    <taglib-uri>/charts.tld</taglib-uri>
    <taglib-location>
    /WEB-INF/tlds/chart-tags-1.3beta.tld
    </taglib-location>
    </taglib>

    給出這個說明后,JSP頁面可通過下面的簡化形式使用標簽庫。

    <%@ taglib uri="/charts.tld" prefix="somePrefix" %>

    14 指定應用事件監聽程序

    應用事件監聽器程序是建立或修改servlet環境或會話對象時通知的類。它們是servlet規范的版本2.3中的新內容。這里只簡單地說明用來向Web應用注冊一個監聽程序的web.xml的用法。
    注冊一個監聽程序涉及在web.xml的web-app元素內放置一個listener元素。在listener元素內,listener-class元素列出監聽程序的完整的限定類名,如下所示:

    <listener>
    <listener-class>package.ListenerClass</listener-class>
    </listener>

    雖然listener元素的結構很簡單,但請不要忘記,必須正確地給出web-app元素內的子元素的次序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外,因為應用生存期監聽程序是serlvet規范的2.3版本中的新內容,所以必須使用 web.xml DTD的2.3版本,而不是2.2版本。
    例如,程序清單5-20給出一個名為ContextReporter的簡單的監聽程序,只要Web應用的Servlet-Context建立(如裝載Web應用)或消除(如服務器關閉)時,它就在標準輸出上顯示一條消息。程序清單5-21給出此監聽程序注冊所需要的web.xml文件的一部分。

    程序清單5-20 ContextReporterjava

    package moreservlets;
    
    import javax.servlet.*;
    import java.util.*;
    
    /** Simple listener that prints a report on the standard output
    * when the ServletContext is created or destroyed.
    * <P>
    * Taken from More Servlets and JavaServer Pages
    * from Prentice Hall and Sun Microsystems Press,
    * http://www.moreservlets.com/.
    * ? 2002 Marty Hall; may be freely used or adapted.
    */
    
    public class ContextReporter implements ServletContextListener {
    public void contextInitialized(ServletContextEvent event) {
    System.out.println("Context created on " +
    new Date() + ".");
    }
    
    public void contextDestroyed(ServletContextEvent event) {
    System.out.println("Context destroyed on " +
    new Date() + ".");
    }
    }

    程序清單5-21 web.xml(聲明一個監聽程序的摘錄)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    <!-- ... -->
    <filter-mapping> … </filter-mapping>
    <listener>
    <listener-class>package.ListenerClass</listener-class>
    </listener>
    <servlet> ... </servlet>
    <!-- ... -->
    </web-app>

    15 J2EE元素

    本節描述用作J2EE環境組成部分的Web應用的web.xml元素。這里將提供一個簡明的介紹,詳細內容可以參閱http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf的Java 2 Plantform Enterprise Edition版本1.3規范的第5章。
    l distributable
    distributable 元素指出,Web應用是以這樣的方式編程的:即,支持集群的服務器可安全地在多個服務器上分布Web應用。例如,一個可分布的應用必須只使用 Serializable對象作為其HttpSession對象的屬性,而且必須避免用實例變量(字段)來實現持續性。distributable元素直接出現在discription元素之后,并且不包含子元素或數據,它只是一個如下的標志。

    <distributable />

    l resource-env-ref
    resource -env-ref元素聲明一個與某個資源有關的管理對象。此元素由一個可選的description元素、一個resource-env-ref- name元素(一個相對于java:comp/env環境的JNDI名)以及一個resource-env-type元素(指定資源類型的完全限定的類),如下所示:

    <resource-env-ref>
    <resource-env-ref-name>
    jms/StockQueue
    </resource-env-ref-name>
    <resource-env-ref-type>
    javax.jms.Queue
    </resource-env-ref-type>
    </resource-env-ref>

    l env-entry
    env -entry元素聲明Web應用的環境項。它由一個可選的description元素、一個env-entry-name元素(一個相對于java: comp/env環境JNDI名)、一個env-entry-value元素(項值)以及一個env-entry-type元素(java.lang程序包中一個類型的完全限定類名,java.lang.Boolean、java.lang.String等)組成。下面是一個例子:

    <env-entry>
    <env-entry-name>minAmout</env-entry-name>
    <env-entry-value>100.00</env-entry-value>
    <env-entry-type>minAmout</env-entry-type>
    </env-entry>

    l ejb-ref
    ejb -ref元素聲明對一個EJB的主目錄的應用。它由一個可選的description元素、一個ejb-ref-name元素(相對于java: comp/env的EJB應用)、一個ejb-ref-type元素(bean的類型,Entity或Session)、一個home元素(bean的主目錄接口的完全限定名)、一個remote元素(bean的遠程接口的完全限定名)以及一個可選的ejb-link元素(當前bean鏈接的另一個 bean的名稱)組成。
    l ejb-local-ref
    ejb-local-ref元素聲明一個EJB的本地主目錄的引用。除了用local-home代替home外,此元素具有與ejb-ref元素相同的屬性并以相同的方式使用

    posted @ 2006-06-02 12:48 MyJavaWorld 閱讀(229) | 評論 (0)編輯 收藏

    用java.util.zip制作zip壓縮文件時,如果制作的壓縮文件有中文文件名或中文目錄,用WinZip、WinRar解壓時會有亂碼, 同樣,用java.util.zip解壓WinZip、WinRar打包的壓縮文件時,中文也是亂碼,主要原因是因為java.util.zip使用編碼和WinZip和WinRar使用的不同,在網上找了半天,發現只有兩種解決方法:
    1、修改import java.util.zip.ZipInputStream和ZipOutputStream。
    2、使用Apache Ant里提供的zip工具。
    -------------------------------------
    已找到解決方法,就是用Ant的zip來實現,Ant里面可以指定編碼,而java.util.zip是寫死了的,只能用UTF-8,呵呵
    -------------------------------
    不要使用java.util.zip的包,用ant.jar放到classpath中

    //在classpath中引入ant.jar的包
    import java.io.*;?
    import java.util.*;
    import java.io.File;
    import org.apache.tools.zip.*;

    public? class? CDGGzip?
    {?
    ? //boolean? packFrame? =? false;?
    ? private File srcPath =new File("d:"+File.separator+"邢曉寧");
    ? private String outFilename=new String("d:"+File.separator+"邢曉寧.zip");
    private int len=srcPath.listFiles().length;
    private String[] filenames = new String[len];
    public void setSrcPath(String src){
    ?? srcPath=new File(src);
    ? }
    ? public File getSrcPath(){
    ? return srcPath;
    ? }
    public void setOutFilename(String out){
    ?? outFilename=out;
    ? }
    ? public String getOutFilename(){
    ? return outFilename;
    ? }?

    ? public void gzip(){
    byte[] buf = new byte[1024];
    ? try {
    ? File[]? files? =? srcPath.listFiles();
    ? for(int? i=0;i<len;i++)
    ? {
    ? //if(!files[i].isDirectory())
    filenames[i]=srcPath.getPath()+File.separator+files[i].getName();
    }
    ? ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));
    ? for (int i=0; i<filenames.length; i++)
    ? {
    ? FileInputStream in = new FileInputStream(filenames[i]);
    ? out.putNextEntry(new org.apache.tools.zip.ZipEntry(files[i].getName()));
    ? int len;
    ? while ((len = in.read(buf)) > 0)
    ? {
    ? out.write(buf, 0, len);
    ? }

    ? out.closeEntry();
    ? in.close();
    ????? }

    ????? out.close();
    ??? }
    ??? catch (IOException e)
    ??? {
    ??? System.out.println(e);
    ??? }
    ? }
    ?
    ? public static void main(String arg[]){
    ? CDGGzip cdggzip=new CDGGzip();
    ? cdggzip.gzip();
    ? }
    ?
    }

    posted @ 2006-05-29 19:08 MyJavaWorld 閱讀(432) | 評論 (0)編輯 收藏
    import?java.util.*;

    import?java.util.zip.*;

    import?java.io.*;

    class?TestZip?

    {

    public?void?zip(String?zipFileName,String?inputFile)throws?Exception{

    zip(zipFileName,new?File(inputFile));

    }

    public?void?zip(String?zipFileName,File?inputFile)throws?Exception{

    ZipOutputStream?out=new?ZipOutputStream(new?FileOutputStream(zipFileName));

    zip(out,inputFile,"");

    System.out.println("zip?done");

    out.close();

    }



    public?void?unzip(String?zipFileName,String?outputDirectory)throws?Exception{
    ZipInputStream?in=new?ZipInputStream(new?FileInputStream(zipFileName));

    ZipEntry?z;

    while?((z=in.getNextEntry()?)!=?null)

    {

    System.out.println("unziping?"+z.getName());

    if?(z.isDirectory())

    {

    String?name=z.getName();

    name=name.substring(0,name.length()-1);

    File?f=new?File(outputDirectory+File.separator+name);

    f.mkdir();

    System.out.println("mkdir?"+outputDirectory+File.separator+name);

    }

    else{

    File?f=new?File(outputDirectory+File.separator+z.getName());

    f.createNewFile();

    FileOutputStream?out=new?FileOutputStream(f);

    int?b;

    while?((b=in.read())?!=?-1)

    out.write(b);

    out.close();

    }

    }



    in.close();

    }



    public?void?zip(ZipOutputStream?out,File?f,String?base)throws?Exception{

    System.out.println("Zipping??"+f.getName());

    if?(f.isDirectory())

    {

    File[]?fl=f.listFiles();

    out.putNextEntry(new?ZipEntry(base+"/"));

    base=base.length()==0?"":base+"/";

    for?(int?i=0;i<fl.length?;i++?)

    {

    zip(out,fl,base+fl.getName());

    }

    }

    else

    {

    out.putNextEntry(new?ZipEntry(base));

    FileInputStream?in=new?FileInputStream(f);

    int?b;

    while?((b=in.read())?!=?-1)

    out.write(b);

    in.close();

    }



    }

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

    {

    try{

    TestZip?t=new?TestZip();

    t.zip("c:\\test.zip","c:\\test");

    t.unzip("c:\\test.zip","c:\\test2");

    }

    catch(Exception?e){e.printStackTrace(System.out);}

    }

    }
    posted @ 2006-05-29 17:47 MyJavaWorld 閱讀(488) | 評論 (0)編輯 收藏
      1、?EasyJF開源團隊官方網站,網址:http://www.easyjf.com
      2、?Java研究組織(JR) ,網址:http://www.javaresearch.org
    ???? 3,
    posted @ 2006-05-29 17:31 MyJavaWorld 閱讀(157) | 評論 (0)編輯 收藏
    僅列出標題
    共3頁: 上一頁 1 2 3 
    主站蜘蛛池模板: 夜夜爽妓女8888视频免费观看| 亚洲福利视频网址| 特色特黄a毛片高清免费观看 | 免费在线观看亚洲| 国产一区二区三区在线免费观看| 久久精品国产亚洲av四虎| 成av免费大片黄在线观看| 亚洲综合av永久无码精品一区二区| 一级做受视频免费是看美女| 精品国产人成亚洲区| 国产精品青草视频免费播放| 亚洲精品狼友在线播放| 免费无码又爽又刺激高潮软件| 日本视频一区在线观看免费| 亚洲一级毛片免费观看| 成人毛片免费在线观看| 国产亚洲人成在线影院| 亚洲免费日韩无码系列| 国产成人精品亚洲日本在线 | 99热在线观看免费| 亚洲一区影音先锋色资源| 亚洲三级在线免费观看| 亚洲熟妇无码八V在线播放| 亚洲AV成人潮喷综合网| 亚洲成av人片天堂网无码】| 亚洲国产成人久久一区久久| 最好免费观看高清在线| 亚洲人成毛片线播放| 免费人妻av无码专区| 免费精品一区二区三区第35 | 一个人看的www在线观看免费| 亚洲AV综合永久无码精品天堂| 伊人久久亚洲综合影院| 污视频在线观看免费| 亚洲a∨无码一区二区| 国产成人精品免费视频动漫| 亚洲日韩在线中文字幕综合 | 久久亚洲精品无码网站| 亚洲人成网77777亚洲色| 免费看韩国黄a片在线观看| 特级毛片A级毛片100免费播放|