配置 web.xml 部署描述符

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

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

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

关于部署描述符

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

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

下面是 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 之间的映射。Web 服务器使用该配置确定 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>

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

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

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

JSPs

应用可以使用 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>

可以使用 <taglib> 元素来安装 JSP 标记库。标记库具有指向 JSP 标记库描述符 (TLD) 文件的路径 (<taglib-location>) 以及 JSP 用于选择要加载的库的 URI (<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-name> 元素(与所声明 Servlet 的名称匹配以在调用 Servlet 时应用该过滤器)。

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

错误处理程序

通过使用部署描述符,您可以自定义在发生错误时服务器向用户发送的内容。在服务器将要发送特定 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>

不支持的 web.xml 功能

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

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