Heim >Backend-Entwicklung >XML/RSS-Tutorial >Detailliertes Beispiel für die Konfiguration von Web.xml

Detailliertes Beispiel für die Konfiguration von Web.xml

Y2J
Y2JOriginal
2017-04-24 10:38:121862Durchsuche

1 Header- und Root-Elemente definieren

Bereitstellungsdeskriptordateien müssen wie alle XML-Dateien mit einem XML-Header beginnen. Dieser Header deklariert die verwendbare XML-Version und gibt die Zeichenkodierung der Datei an.
Die DOCYTPE-Anweisung muss unmittelbar nach dieser Kopfzeile stehen. Diese Deklaration teilt dem Server die Version der anwendbaren Servlet-Spezifikation mit (z. B. 2.2 oder 2.3) und gibt die DTD(Dokument-Typdefinition) an, die die Syntax regelt für den restlichen Inhalt dieser Datei Dokumenttypdefinition).
Das oberste Element (Stammelement) aller Bereitstellungsdeskriptordateien ist web-app. Bitte beachten Sie, dass bei XML-Elementen im Gegensatz zu HTML die Groß-/Kleinschreibung beachtet wird. Daher sind sowohl „web-App“ als auch „WEB-APP“ illegal und „web-app“ muss in Kleinbuchstaben geschrieben werden.

2 Die Reihenfolge der Elemente in der Bereitstellungsdeskriptordatei

XML-Elemente berücksichtigen nicht nur die Groß-/Kleinschreibung, sondern auch die Reihenfolge, in der sie in anderen Elementen erscheinen. Beispielsweise muss der XML-Header das erste Element in der Datei sein, die DOCTYPE-Deklaration muss das zweite Element sein und das Web-App-Element muss das dritte Element sein. Innerhalb von Web-App-Elementen ist auch die Reihenfolge der Elemente wichtig. Server erzwingen diese Reihenfolge nicht unbedingt, sie ermöglichen jedoch (und einige Server tun dies auch), die Ausführung von Webanwendungen, die Elemente enthalten, die nicht in der richtigen Reihenfolge sind, vollständig zu verweigern. Das bedeutet, dass web.xml-Dateien, die eine nicht standardmäßige Elementreihenfolge verwenden, nicht portierbar sind.
Die folgende Liste gibt die erforderliche Reihenfolge für alle rechtlichen Elemente an, die direkt im Web-App-Element erscheinen können. In dieser Liste heißt es beispielsweise, dass das Servlet-Element vor allen Servlet-Mapping-Elementen erscheinen muss. Beachten Sie, dass alle diese Elemente optional sind. Daher können Sie ein Element weglassen, es aber nicht an einer falschen Position platzieren.
l-Symbol Das Symbolelement gibt den Speicherort von einer und zwei Bilddateien an, die von IDE- und GUI-Tools zur Darstellung von Webanwendungen verwendet werden.
l display-name Das Element display-name stellt einen Namen bereit, den GUI-Tools zum Markieren dieser bestimmten Webanwendung verwenden können.
l Beschreibung Das Beschreibungselement enthält einen beschreibenden Text dazu.
l context-param Das context-param-Element deklariert anwendungsbezogene Initialisierungsparameter. Der
l-Filter Das Filterelement ordnet einen Namen einer Klasse zu, die die javax.servlet.FilterSchnittstelle implementiert.
l Filterzuordnung Sobald Sie einen Filter benannt haben, verknüpfen Sie ihn mithilfe des Filterzuordnungselements mit einem oder mehreren Servlets oder JSP Seiten.
l Listener-Servlet Version 2.3 der API fügt Unterstützung für Ereignis--Listener hinzu, die zum Erstellen, Ändern und Löschen Sitzungen oder Servlet-Umgebungen verwendet werden. Lassen Sie sich benachrichtigen Wann. Das Listener-Element gibt die Ereignis-Listener-Klasse an.
l Servlet Wenn Sie Initialisierungsparameter angeben oder die URL für ein Servlet oder eine JSP-Seite anpassen, müssen Sie zuerst das Servlet oder die JSP-Seite benennen. Um diese Aufgabe zu erfüllen, wird das Servlet-Element verwendet.
l Servlet-Mapping Der Server stellt im Allgemeinen eine Standard-URL für Servlets bereit: http://host/webAppPrefix/servlet/ServletName. Diese URL wird jedoch häufig geändert, damit das Servlet auf Initialisierungsparameter zugreifen kann oder um relative URLs einfacher verarbeiten zu können. Wenn Sie die Standard-URL ändern, verwenden Sie das Servlet-Mapping-Element.
l session-config Wenn auf eine Sitzung über einen bestimmten Zeitraum nicht zugegriffen wurde, kann der Server sie verwerfen, um Speicherplatz zu sparen. Der Timeout-Wert für ein einzelnes Sitzungsobjekt kann explizit mithilfe der setMaxInactiveInterval-Methode von HttpSession festgelegt werden, oder es kann mithilfe des session-config-Elements ein Standard-Timeout-Wert angegeben werden.
l Mime-Mapping Wenn eine Webanwendung spezielle Dateien im Sinn hat und sicherstellen möchte, dass ihnen ein bestimmter MIME-Typ zugewiesen wird, bietet das Mime-Mapping-Element diese Garantie.
l welcom-file-list Das Element „welcome-file-list“ weist den Server an, welche Datei er verwenden soll, wenn er eine URL empfängt, die auf einen Verzeichnisnamen anstelle eines Dateinamens verweist.
l error-page Mit dem Element „error-page“ können Sie die Seite angeben, die angezeigt werden soll, wenn ein bestimmter HTTP-Statuscode zurückgegeben wird oder wenn eine bestimmte Art von Ausnahme ausgelöst wird.
l taglib Das taglib-Element gibt einen Alias ​​für die Tag Library Descriptor-Datei an. Mit dieser Funktion können Sie den Speicherort von TLD-Dateien ändern, ohne die JSP-Seiten zu bearbeiten, die diese Dateien verwenden.
l resources-env-ref Das Element „resource-env-ref“ deklariert ein Verwaltungsobjekt, das sich auf die Ressource bezieht.
l resources-ref Das Element „resource-ref“ deklariert eine externe Ressource, die von einer Ressourcenfabrik verwendet wird.
l security-constraint Das Element security-constraint gibt URLs an, die geschützt werden sollen. Es wird in Verbindung mit dem login-config-Element
l login-config verwendet. Verwenden Sie das login-config-Element, um anzugeben, wie der Server Benutzer autorisieren soll, die versuchen, auf geschützte Seiten zuzugreifen. Es wird in Verbindung mit dem Element „Security-Constraint“ verwendet.
l security-role Das security-role-Element enthält eine Liste von Sicherheitsrollen, die im Unterelement „role-name“ des Elements „security-role-ref“ im Servlet-Element angezeigt werden. Die separate Deklaration von Rollen erleichtert fortgeschrittenen IDEs den Umgang mit Sicherheitsinformationen.
l env-entry Das env-entry-Element deklariert die Umgebungselemente der Webanwendung.
l ejb-ref Das ejb-ref-Element deklariert einen Verweis auf das Home-Verzeichnis des EJB.
l ejb-local-ref Das Element ejb-local-ref deklariert eine Anwendung im lokalen Home-Verzeichnis eines EJB.

3 Zuweisen eines Namens und einer benutzerdefinierten UL

Eine der häufigsten Aufgaben in web.xml besteht darin, einem Servlet oder einer JSP-Seite einen Namen und eine benutzerdefinierte URL zuzuweisen. Verwenden Sie das Servlet-Element, um den Namen zuzuweisen, und verwenden Sie das Servlet-Mapping-Element, um die benutzerdefinierte URL mit dem gerade zugewiesenen Namen zu verknüpfen.
3.1 Zuweisen eines Namens
Um Initialisierungsparameter bereitzustellen, eine benutzerdefinierte URL zu definieren oder dem Servlet oder der JSP-Seite eine Sicherheitsrolle zuzuweisen, müssen Sie dem Servlet oder der JSP-Seite zunächst einen Namen geben. Über das Servlet-Element kann ein Name vergeben werden. Das gebräuchlichste Format umfasst die Unterelemente servlet-name und servlet-class (innerhalb des Web-App-Elements) wie folgt:

Xml-Code

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

Dies bedeutet, dass das Servlet unter WEB-INF/classes/moreservlets/TestServlet den registrierten Namen Test erhalten hat. Einem Servlet einen Namen zu geben hat im Wesentlichen zwei Bedeutungen. Erstens verweisen Initialisierungsparameter, benutzerdefinierte URL-Muster und andere Anpassungen auf dieses Servlet über seinen registrierten Namen und nicht über seinen Klassennamen. Zweitens kann dieser Name in der URL anstelle des Klassennamens verwendet werden. Daher kann unter Verwendung der gerade gegebenen Definition die URL http://host/webAppPrefix/servlet/Test anstelle von http://host/webAppPrefix/servlet/moreservlets.TestServlet verwendet werden.
Denken Sie daran: Bei XML-Elementen muss nicht nur die Groß-/Kleinschreibung beachtet werden, sondern auch die Reihenfolge, in der sie definiert werden, ist wichtig. Beispielsweise müssen alle Servlet-Elemente innerhalb des Web-App-Elements vor allen Servlet-Mapping-Elementen (im nächsten Abschnitt beschrieben) und auch vor den in den Abschnitten 5.6 und 5.11 besprochenen filter- oder dokumentbezogenen Elementen (falls vorhanden) stehen . Ebenso muss das Unterelement servlet-name eines Servlets vor servlet-class stehen. Abschnitt 5.2, „Reihenfolge der Elemente in Bereitstellungsdeskriptordateien“ beschreibt diese erforderliche Reihenfolge.
Listing 5-1 zeigt beispielsweise ein einfaches Servlet namens TestServlet, das sich im Paket moreservlets befindet. Da dieses Servlet Teil einer Webanwendung ist, deren Stammverzeichnis sich in einem Verzeichnis namens „deployDemo“ befindet, wird „TestServlet.class“ in „deployDemo/WEB-INF/classes/moreservlets“ abgelegt. Listing 5-2 zeigt einen Teil der Datei „web.xml“, der in „deployDemo/WEB-INF/“ abgelegt wird. Diese web.xml-Datei verwendet die Elemente servlet-name und servlet-class, um den Namen Test mit TestServlet.class zu verknüpfen. Abbildung 5-1 und Abbildung 5-2 zeigen die Ergebnisse des Aufrufs von TestServlet unter Verwendung der Standard-URL bzw. des registrierten Namens.

Programmauflistung 5-1 TestServlet.java

Java-Code

package moreservlets;       import java.io.*;    import javax.servlet.*;    import javax.servlet.http.*;       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>");        }    }  
package moreservlets;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;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>");}}

Programmauflistung 5-2 web.xml (Auszug mit Angabe des Servlet-Namens)

Xml-Code

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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 Benutzerdefinierte URL definieren
Die meisten Server haben eine Standard-Servlet-URL:
host/webAppPrefix/servlet/packageName.ServletName . Obwohl die Verwendung dieser URL während der Entwicklung praktisch ist, benötigen wir häufig eine andere URL für die Bereitstellung. Beispielsweise benötigen Sie möglicherweise eine URL, die auf der obersten Ebene der Webanwendung angezeigt wird (z. B. host/webAppPrefix/Anyname), und diese URL enthält keine Servlet-Einträge. URLs auf der obersten Ebene vereinfachen die Verwendung relativer URLs. Darüber hinaus erscheint die Top-Level-URL für viele Entwickler kürzer als die längere und umständlichere Standard-URL.
Tatsächlich ist es manchmal notwendig, eine benutzerdefinierte URL zu verwenden. Beispielsweise möchten Sie möglicherweise die Standard-URL-Zuordnung deaktivieren, um Sicherheitsbeschränkungen besser durchzusetzen oder um zu verhindern, dass Benutzer versehentlich auf ein Servlet ohne Initialisierungsparameter zugreifen. Wie greifen Sie auf das Servlet zu, wenn Sie die Standard-URL deaktivieren? Derzeit besteht die einzige Möglichkeit darin, eine benutzerdefinierte URL zu verwenden.
Um eine benutzerdefinierte URL zuzuweisen, verwenden Sie das servlet-mapping-Element und seine Unterelemente servlet-name und url-pattern. Das Servlet-Name-Element stellt einen beliebigen Namen bereit, der verwendet werden kann, um auf das entsprechende Servlet zu verweisen. Das URL-Muster beschreibt die URL relativ zum Stammverzeichnis der Webanwendung. Der Wert des URL-Musterelements muss mit einem Schrägstrich (/) beginnen.
Im Folgenden finden Sie einen einfachen web.xml-Auszug, der die Verwendung der URL host/webAppPrefix/UrlTest anstelle von host/webAppPrefix/servlet/Test oder
host/webAppPrefix/servlet/moreservlets.TestServlet ermöglicht. Beachten Sie, dass der XML-Header, die DOCTYPE-Deklaration und das umschließende Web-App-Element weiterhin erforderlich sind. Bedenken Sie außerdem, dass die Reihenfolge, in der XML-Elemente angezeigt werden, nicht willkürlich ist. Insbesondere müssen Sie alle Servlet-Elemente vor allen Servlet-Mapping-Elementen platzieren.

Xml-Code

<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>  
<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-Muster können auch Platzhalter enthalten. Das folgende Applet weist den Server beispielsweise an, alle Anfragen, die mit dem URL-Präfix der Webanwendung beginnen und mit ..asp enden, an ein Servlet namens BashMS zu senden.

Xml-Code

<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>  
<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 Benennen der JSP-Seite
Da die JSP-Seite in ein Sevlet konvertiert werden muss, ist es selbstverständlich, die JSP-Seite genauso zu benennen Benennen des Servlets. Schließlich könnte eine JSP-Seite wie ein normaler Server von Initialisierungsparametern, Sicherheitseinstellungen oder einer benutzerdefinierten URL profitieren. Obwohl es richtig ist, dass der Hintergrund einer JSP-Seite tatsächlich ein Servlet ist, besteht ein wichtiger Verdacht: Sie kennen den tatsächlichen Klassennamen der JSP-Seite nicht (da das System diesen Namen selbst wählt). Um also eine JSP-Seite zu benennen, ersetzen Sie das jsp-file-Element durch das servlet-calss-Element wie folgt:

Xml-Code

<servlet>       <servlet-name>Test</servlet-name>       <jsp-file>/TestPage.jsp</jsp-file>   </servlet>  
<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

Html代码

<!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>  
<!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代码

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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。只要简单地使用:

Xml代码

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

作为servlet-mapping元素中的模式即可。

例如,程序清单5-5给出了将SorryServlet servlet(程序清单5-6)与所有以http://host/webAppPrefix/servlet/ 开头的URL相关联的部署描述符文件的一部分。

程序清单5-5 web.xml(说明JSP页命名的摘录)

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>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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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

Java代码

package moreservlets;       import java.io.*;    import javax.servlet.*;    import javax.servlet.http.*;       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);        }    }  
package moreservlets;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;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映射项即可,如下所示:

Xml代码

<servlet-mapping>       <servlet-name>invoker</servlet-name>       <url-pattern>/servlet/*</url-pattern>   </servlet-mapping>  
<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文件的一部分。

Xml代码

<!--    <RequsetInterceptor className="org.apache.tomcat.request.InvokerInterceptor" debug="0" prefix="/servlet/" />   -->  
<!--<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"。

Xml代码

<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>  
<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

Java代码

package moreservlets;       import java.io.*;    import javax.servlet.*;    import javax.servlet.http.*;       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>");        }    }  
package moreservlets;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;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代码

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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元素如下所示:

Xml代码

<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>  
<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定义:

Xml代码

<servlet-mapping>       <servlet-name>PageName</servlet-name>       <url-pattern>/RealPage.jsp</url-pattern>   </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

Html代码

<!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");    }    %>  
<!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代码

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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子元素,如下所示:

Xml代码

<context-param>       <param-name>support-email</param-name>       <param-value>blackhole@mycompany.com</param-value>   </context-param>  
<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。下面是一个例子。

Xml代码

<servlet>       <servlet-name> … </servlet-name>       <servlet-class> … </servlet-class> <!-- Or jsp-file -->   <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。

Xml代码

<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>  
<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

Java代码

package moreservlets;       import java.io.*;    import javax.servlet.*;    import javax.servlet.http.*;    import java.util.*;       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() {}    }  
package moreservlets;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import java.util.*;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程序包中)相关联。

Xml代码

<filter>       <filter-name>Reporter</filter-name>       <filter-class>moresevlets.ReportFilter</filter-class>   </filter>  
<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的过滤器。

Xml代码

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

其次,可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如,相面的程序片段指示系统只要访问Web应用中的任意URL,就运行名为Reporter的过滤器。

Xml代码

<filter-mapping>       <filter-name>Reporter</filter-name>       <url-pattern>/*</url-pattern>   </filter-mapping>  
<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项,可看到下面的标准输出形式的调试报告(换行是为了容易阅读)。

程序清单5-12 Web.xml(说明filter用法的摘录)

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>           <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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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。如果两者都没有找到,则结果有赖于所用的服务器(如一个目录列表)。

Xml代码

<welcome-file-list>       <welcome-file>index.jsp</welcome-file>       <welcome-file>index.html</welcome-file>   </welcome-file-list>  
<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错误信息,它表示不能找到该文件,但几乎没提供更多有用的信息。另一方面,可以试一下在http://www.microsoft.com/、http://www.ibm.com/ 处或者特别是在http://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代码

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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目录中所有文档应该受到保护。

Xml代码

<security-constraint>       <web-resource-coolection>       <web-resource-name>Proprietary</web-resource-name>           <url-pattern>/propritary/*</url-pattern>       </web-resource-coolection>   <!-- ... -->   </security-constraint>  
<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(或两者)的用户具有指定资源的访问权。

Xml代码

<security-constraint>       <web-resource-coolection> ... </web-resource-coolection>       <auth-constraint>           <role-name>administrator</role-name>           <role-name>kahuna</role-name>       </auth-constraint>   </security-constraint>  
<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角色。

Xml代码

<tomcat-users>       <user name="joe" password="bigshot" roles="administrator,kahuna" />       <user name="jane" password="enaj" roles="kahuna" />   </tomcat-users>  
<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连接:

Xml代码

<security-constraint>   <!-- ... -->       <user-data-constraint>           <transport-guarantee>CONFIDENTIAL</transport-guarantee>       </user-data-constraint>   </security-constraint>  
<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能够使用这两个名称中的任何一个。

Xml代码

<servlet>   <!-- ... -->       <security-role-ref>           <role-name>boss</role-name> <!-- New alias -->           <role-link>manager</role-link> <!-- Real name -->       </security-role-ref>   </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分钟)。

Xml代码

<session-config>       <session-timeout>180</session-timeout>   </session-config>  
<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的图像。下面举一个例子:

Xml代码

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

l display-name
display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。
104ce0f86471f18553dacb332199720eRare Books6016cc98de5b53c0cfd1cdb1cf6f5e32
l description
description元素提供解释性文本,如下所示:

Xml代码

<description>   This Web application represents the store developed for rare-books.com, an online bookstore specializing in rare and limited-edition books.    </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结尾的文件。

Xml代码

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

或许,你的Web应用希望重载(override)标准的映射。例如,下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本(text/plain)而不是作为PostScript(application/postscript)。

Xml代码

<mime-mapping>       <extension>ps</extension>       <mime-type>application/postscript</mime-type>   </mime-mapping>  
<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元素内包含下列内容。

Xml代码

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

给出这个说明后,JSP页面可通过下面的简化形式使用标签库。
58ed685e219d561b3e65f326faac48cb

14 指定应用事件监听程序

应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内,listener-class元素列出监听程序的完整的限定类名,如下所示:

Xml代码

<listener>       <listener-class>package.ListenerClass</listener-class>   </listener>  
<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

Java代码

package moreservlets;       import javax.servlet.*;    import java.util.*;       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() + ".");        }    }  
package moreservlets;import javax.servlet.*;import java.util.*;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代码

<?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>  
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-appPUBLIC "-//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元素之后,并且不包含子元素或数据,它只是一个如下的标志。
48089aeaade43177b16892cbe66a80b9
l resource-env-ref
resource -env-ref元素声明一个与某个资源有关的管理对象。此元素由一个可选的description元素、一个resource-env-ref- name元素(一个相对于java:comp/env环境的JNDI名)以及一个resource-env-type元素(指定资源类型的完全限定的类),如下所示:

Xml代码

<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>  
<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等)组成。下面是一个例子:

Xml代码

<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>  
<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元素相同的属性并以相同的方式使用。

给你的session加个监听器

今天一个学生问我怎么实现在网页里显示在线用户的名称——他已经使用了session,但是无法处理用户离开的情况,然后导致在线用户列表的无限增大。跟他说了自己在application中进行超时检查,更新application的时候就比较当前所有列表中的session是否超过自己指定的时间间隔。后来想了想,又给他提了使用给session加监听器的方法。但是提的时候自己也没有做过,所以只是说这种方式很复杂,建议他还是自己进行超时检查。刚才又看了看资料,发现实际上给session加监听器的方式很简单,不禁觉得自己有点误人子弟了,现在将方法写在这,借以告诫自己以后要严谨。
首先写一个SessionBinder类,它实现了HttpSessionBindingListener接口的valueBound方法和valueUnbound方法,示例代码如下:

Java代码

public class SessionBinder implements HttpSessionBindingListener {        public void valueBound(HttpSessionBindingEvent event){        //you can do anything you want!this method will be called when this binder is bind with any session.        }           public void valueUnbound(HttpSessionBindingEvent event) {        //you can do something while this session is invalidate        }    }  
public class SessionBinder implements HttpSessionBindingListener {public void valueBound(HttpSessionBindingEvent event){//you can do anything you want!this method will be called when this binder is bind with any session.}public void valueUnbound(HttpSessionBindingEvent event) {//you can do something while this session is invalidate}}

现在写好了SessionBinder,我们现在选择在一个servlet中向session中加入这个监听器——在jsp中的代码书写与此相同
//省略前面的代码,此操作可能发生在servlet的doGet方法中,也可能是doPost方法中

Java代码

HttpSession session = req.getSession(true);//首先获得需要加入监听器的session对象,req是HttpRequest对象    SessionBinder sb = new SessionBinder();//建立一个监听器对象    session.putValue("BinderObject",sb);//将监听器加入此session中,从此时开始执行sb的valueBound方法  
    HttpSession session = req.getSession(true);//首先获得需要加入监听器的session对象,req是HttpRequest对象SessionBinder sb = new SessionBinder();//建立一个监听器对象session.putValue("BinderObject",sb);//将监听器加入此session中,从此时开始执行sb的valueBound方法

//省略后面的代码
随后,如果整个session超时或者被用户中止之后,sb的valueUnbound自动执行

Das obige ist der detaillierte Inhalt vonDetailliertes Beispiel für die Konfiguration von Web.xml. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn