配置 web.xml 部署描述符

将 Java 应用部署到包含 Eclipse Jetty 9/ servlet 3 服务器的运行时时,才会用到 web.xml 文件。如需了解详情,请参阅 Eclipse Jetty 9.3 运行时

Java 网络应用使用部署描述符文件确定如何将网址映射到 Servlet,哪些网址需要身份验证以及其他信息。该文件命名为 web.xml,位于应用 WEB-INF/ 目录下的 WAR 中。web.xml 是网络应用 servlet 标准的一部分。

如需详细了解 web.xml 标准,请参阅 Metawerx web.xml 参考 WikiServlet 规范

关于部署描述符

网络应用的部署描述符描述了应用的类、资源和配置,以及网络服务器如何使用它们处理网络请求。当网络服务器收到应用请求时,它使用部署描述符将请求网址映射到应处理该请求的代码。

部署描述符是名为 web.xml 的文件。它位于应用 WEB-INF/ 目录下的 WAR 中。该文件为 XML 文件,其根元素是 <web-app>

下面是 web.xml 的一个简单示例,其中将所有网址路径 (/*) 映射到 Servlet 类 mysite.server.ComingSoonServlet

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>comingsoon</servlet-name>
        <servlet-class>mysite.server.ComingSoonServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>comingsoon</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Servlet 和网址路径

web.xml 定义网址路径与通过这些路径处理请求的 servlet 之间的映射。网络服务器使用此配置来标识用于处理给定请求的 servlet,并调用与请求方法相对应的类方法(例如,用于 HTTP GET 请求的 doGet() 方法)。

要将网址映射到 servlet,您需要用 <servlet> 元素声明 servlet,然后通过 <servlet-mapping> 元素定义从网址路径到 servlet 声明的映射。

<servlet> 元素声明 servlet,其中包括用文件中的其他元素指代 servlet 的名称,用于 servlet 的类以及初始化参数。您可以使用具有不同初始化参数的相同类声明多个 Servlet。每个 Servlet 的名称在部署描述符中必须是唯一的。

    <servlet>
        <servlet-name>redteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>red</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#CC0000</param-value>
        </init-param>
    </servlet>

    <servlet>
        <servlet-name>blueteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>blue</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#0000CC</param-value>
        </init-param>
    </servlet>

<servlet-mapping> 元素用于指定网址格式以及已声明 servlet 的名称(用于网址与格式匹配的请求)。网址格式可以在格式开头或结尾使用星号 (*) 以指示零个或多个任意字符。(该标准不支持在字符串中间使用通配符,并且不允许在一个格式中使用多个通配符。)格式会与网址的完整路径匹配,从域名后面的正斜杠 (/) 开始(含正斜杠)。

    <servlet-mapping>
        <servlet-name>redteam</servlet-name>
        <url-pattern>/red/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>blueteam</servlet-name>
        <url-pattern>/blue/*</url-pattern>
    </servlet-mapping>

在该示例中,TeamServlet 类处理了网址 http://www.example.com/blue/teamProfile 的请求,其中 teamColor 参数等于 bluebgColor 参数等于 #0000CC。servlet 可以使用 ServletRequest 对象的 getPathInfo() 方法获取网址路径中与通配符匹配的部分。

Servlet 可以访问其初始化参数,方法是使用自己的 getServletConfig() 方法获取其 servlet 配置,然后以参数形式使用参数名称来对配置对象调用 getInitParameter() 方法。

        String teamColor = getServletConfig().getInitParameter("teamColor");

JSP

应用可以使用 JavaServer Pages (JSP) 实现网页。JSP 是混合使用静态内容(如 HTML)和 Java 代码定义的 Servlet。

App Engine 支持 JSP 自动编译和网址映射。应用 WAR 中文件名以 .jsp 结尾的 JSP 文件(在 WEB-INF/ 外部)自动编译为 Servlet 类,然后映射到与从 WAR 根目录到 JSP 文件的路径等效的网址路径。例如,如果应用在其 WAR 的 register/ 子目录中包含一个名为 start.jsp 的 JSP 文件,App Engine 将编译该文件并将其映射到网址路径 /register/start.jsp

如果需要更好地控制如何将 JSP 映射到网址,您可以在部署描述符中使用 <servlet> 元素声明它,从而明确指定映射。您可以使用从 WAR 根目录到 JSP 文件的路径指定 <jsp-file> 元素,而不是 <servlet-class> 元素。JSP 的 <servlet> 元素可以包含初始化参数。

    <servlet>
        <servlet-name>register</servlet-name>
        <jsp-file>/register/start.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
        <servlet-name>register</servlet-name>
        <url-pattern>/register/*</url-pattern>
    </servlet-mapping>

注意:如果 JSP 位于应用的根目录中,则 <jsp-file> 必须以正斜杠 (/) 开头。

您可以安装具有 <taglib> 元素的 JSP 标记库。标记库具有指向 JSP 标记库描述符 (TLD) 文件的路径 (<taglib-location>) 和 JSP 用于选择要加载的库的网址 (<taglib-uri>)。请注意,App Engine 提供 JavaServer Pages 标准标记库 (JSTL),您无需安装。

    <taglib>
        <taglib-uri>/escape</taglib-uri>
        <taglib-location>/WEB-INF/escape-tags.tld</taglib-location>
    </taglib>

欢迎文件列表

当网站的网址表示指向 WAR 中的静态文件或 JSP 的路径时,通常最好让目录路径也提供一些有用的信息。用户如果访问网址路径 /help/accounts/password.jsp 是为了获取帐号密码的相关信息,则可能会尝试访问 /help/accounts/ 以查找介绍帐户系统文档的页面。部署描述符可以指定一个文件名列表;在用户访问表示 WAR 子目录(尚未显式映射到 Servlet)的路径时,服务器应尝试检查这些文件。servlet 标准将其称为“欢迎文件列表”。

例如,如果用户访问网址路径 /help/accounts/,则部署描述符中的以下 <welcome-file-list> 元素会告知服务器检查 help/accounts/index.jsphelp/accounts/index.html 后再报告网址不存在:

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

过滤器

过滤器是一个用于处理请求的类(与 servlet 类似),但可能允许使用其他过滤器或 servlet 继续处理请求。过滤器可以执行一个辅助任务,如日志记录、执行专用身份验证检查或在调用 Servlet 之前为请求或响应对象添加注释。通过使用过滤器,您可以从部署描述符中编写请求处理任务。

过滤器类实现了 javax.servlet.Filter 接口(包括 doFilter() 方法)。下面是一个简单的过滤器实现,它可记录消息并将控制权沿链(可能包括其他过滤器或 Servlet)向下传递,如部署描述符所述:

package mysite.server;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class LogFilterImpl implements Filter {

    private FilterConfig filterConfig;
    private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {
        log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
            + " request");

        filterChain.doFilter(request, response);
    }

    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    public void destroy() {}

}

与 Servlet 类似,您可以在部署描述符中配置过滤器,方法是先使用 <filter> 元素声明过滤器,然后再通过 <filter-mapping> 元素将其映射到网址格式。也可以将过滤器直接映射到其他 Servlet。

<filter> 元素包含 <filter-name><filter-class> 和可选的 <init-param> 元素。

    <filter>
        <filter-name>logSpecial</filter-name>
        <filter-class>mysite.server.LogFilterImpl</filter-class>
        <init-param>
            <param-name>logType</param-name>
            <param-value>special</param-value>
        </init-param>
    </filter>

<filter-mapping> 元素包含下列内容:与所声明过滤器名称相匹配的 <filter-name> 以及将过滤器应用于网址的 <url-pattern> 元素,或者匹配所声明 servlet 的名称以在调用时应用该过滤器的 <servlet-name> 元素。

    <!-- Log for all URLs ending in ".special" -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <url-pattern>*.special</url-pattern>
    </filter-mapping>

    <!-- Log for all URLs that use the "comingsoon" servlet -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <servlet-name>comingsoon</servlet-name>
    </filter-mapping>

注意:即使路径与 filter-mapping 模式匹配,也不会对静态资源调用过滤器。可以将静态文件直接提供给浏览器。

错误处理程序

通过使用部署描述符,您可以自定义在发生错误时服务器向用户发送的内容。在服务器将要发送特定 HTTP 状态代码或 Servlet 引发特定 Java 异常时,服务器可以显示一个替代页面位置。

<error-page> 元素包含 <error-code> 元素(值为诸如 500 之类的 HTTP 错误代码)或 <exception-type> 元素(值为预期异常的类名称,如 java.io.IOException)。它还包含 <location> 元素,其中含有发生错误时要显示的资源的网址路径。

    <error-page>
        <error-code>500</error-code>
        <location>/errors/servererror.jsp</location>
    </error-page>

注意:目前无法为某些错误情况配置自定义错误处理程序。具体来说,在没有为网址定义 Servlet 映射时,无法自定义 404 响应页面;无法自定义 403 配额错误页面;或者无法自定义在发生 App Engine 内部错误后显示的 500 服务器错误页面。

不支持的 web.xml 功能

App Engine 不支持以下 web.xml 功能:

  • App Engine 支持用于进行 servlet 声明的 <load-on-startup> 元素。但是,载入实际上是在网络服务器实例处理第一个请求期间发生的,而不是在之前发生。
  • 某些部署描述符元素可能会采用要在 IDE 中使用的直观易懂的显示名称、描述和图标。App Engine 不使用这些内容,并会忽略它们。
  • App Engine 不支持 JNDI 环境变量( <env-entry> )。
  • App Engine 不支持 EJB 资源( <resource-ref> )。
  • 不支持销毁 servlet、servlet 上下文或过滤器的通知。
  • <distributable> 元素将被忽略。
  • 不支持使用 <run-at> 的 Servlet 调度。
  • 不支持安全约束:如需了解等效功能,请参阅书架教程
  • web.xml 中不支持 CONFIDENTIAL。