简介
web.xml即部署描述符,位于WEB-INF目录下。在Servlet3以上版本有提供了注解的方式部署Servlet,因此web.xml是可选的。web.xml大概框架如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" metadata-complete="true"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
...
</web-app>
</web-app>是根节点,xmlns指定该命名空间的前缀为空字符串,xsi:schemaLocation指定了web.xml的schema的位置,version指定了Servlet的版本。metadata-complete是可选的,默认是false。如果metadata-complete设置为true,则忽略Servlet注解和Web Fragment,否则会扫描Servlet注解和Web Fragment。启动程序时时,是按照listener -> filter -> servlet顺序加载的。
核心元素
context-param
用来声明给ServletContext的参数,这个元素一般包含param-name(参数名称)和param-value(参数值),ServletContext#getInitParameter方法可以获取到这类元素的值。可以有多个context-param,但是参数名称必须是唯一的,ServletContext#getInitParameterNames方法可以返回所有的参数名称。
listener
用来声明一个监听器,包含一个listener-class元素。
filter
用来声明一个过滤器,这个元素一般包含以下几个元素。
filter-name定义了过滤器的名字,在整个应用程序中必须是唯一的。
filter-class定义了过滤器的完全限定类名。
init-param用于给过滤器设置参数,这个元素包含param-name(参数名称)和param-value(参数值),FilterConfig#getInitParameter方法可以获取到这类元素的值。可以有多个init-param,但是参数名称必须是唯一的,FilterConfig#getInitParameterNames方法可以返回所有的参数名称。
async-supported,值为true或者false,表示这个过滤器是否支持异步处理。
filter-mapping
用来将一个过滤器映射到一个url-pattern或者Servlet,这个元素一般包含以下几个元素。
filter-name表示过滤器的名字,可选的值为filter元素中定义的filter-name。
url-pattern表示url模式,当一个请求发送到Servlet容器的时候,容器先会将请求的url减去当前应用根路径作为servlet path,servlet path符合url-pattern的请求将由这个过滤器处理。可以有多个url-pattern元素。可以使用通配符*,但是通配符的用法是固定的,只能是以 /* 结尾或者 *. 开头这样的。后缀一般有三种写法,精确路径(/或者/a/b),目录(/a/b/*),扩展名(*.jpg)。
servlet-name定义了Servlet的名字,可选的值为servlet元素中定义的servlet-name。
dispatcher表示过滤器适用的请求类型。可选值为FORWARD、REQUEST、INCLUDE、ASYNC、ERROR,可以在一个filter-mapping中加入任意数目的dispatcher,默认值是REQUEST。FORWARD表示RequestDispatcher#forward发出的请求,REQUEST表示客户端发出的请求,INCLUDE表示RequestDispatcher#include发出的请求,ASYNC表示AsyncContext发出的请求,ERROR表示error page元素发出的请求。
servlet
用来声明一个Servlet,这个元素一般包含以下几个元素。
servlet-name定义了Servlet的名字,在整个应用程序中必须是唯一的。
servlet-class定义了Servlet的完全限定类名。
init-param用于给Servlet设置参数,这个元素包含param-name(参数名称)和param-value(参数值),ServletConfig#getInitParameter方法可以获取到这类元素的值。可以有多个init-param,但是参数名称必须是唯一的,ServletConfig#getInitParameterNames方法可以返回所有的参数名称。
load-on-startup可选,如果设置了这个元素,那么在程序启动时将会加载Servlet到内存中并调用其初始化方法init,而不是等到第一次请求Servlet时才加载和初始化。值如果为空和负数,那么将由容器决定何时加载。如果有多个Servlet同时设置了这个元素,那么值比较小的将优先加载,如果值一样,那么将无法确定哪个Servlet先加载。
async-supported,值为true或者false,表示这个Servlet是否支持异步处理。
enabled,值为true或者false,表示这个Servlet是否可用。
servlet-mapping
用来将一个Servlet映射到一个url-pattern,这个元素一般包含以下几个元素。
servlet-name表示Servlet的名字,可选的值为servlet元素中定义的servlet-name。
url-pattern表示url模式,当一个请求发送到Servlet容器的时候,容器先会将请求的url减去当前应用根路径作为servlet path,servlet path符合url-pattern的请求将由这个Servlet处理。可以有多个url-pattern元素。可以使用通配符*,但是通配符的用法是固定的,只能是以 /* 结尾或者 *. 开头这样的。后缀一般有四种写法,精确路径(/a/b),目录(/a/b/*),扩展名(*.jpg),默认(/)。
distributable
用来声明这个应用程序会被部署到分布式容器中。
error-page
用来声明http错误码或者Java异常类型发生时应该返回的资源,这个元素一般包含以下几个元素。
error-code定义了一个http错误码。
exception-type定义了一个Java异常的完全限定类名。
location资源路径,必须以 / 开头。
login-config
用来声明验证用法的方法,这个元素一般包含以下几个元素。
auth-method表示验证方法,可选值为BASIC、DIGEST、FORM、CLIENT CERT。
realm-name表示BASIC和DIGEST验证中使用的realm名字。
form-login-config表示FORM验证配置,包含form-login-page(登录页面)和form-error-page(错误页面)元素,这两个元素必须以 / 开头。
mime-mapping
用来请求url的扩展名映射到某个MIME类型,以避免客户端如浏览器自动打开或者运行下载的文件,这个元素一般包含以下几个元素。
extension表示扩展名。
mime-type表示MIME类型。
session-config
用来为javax.servlet.http.HttpSession设置参数,这个元素一般session-timeout元素。
session-timeout定义了会话超时时间,单位为分钟,必须为整数,如果为0或者负数,那么会话将永远不会超时。
welcome-file-list
用来声明当用户请求应用的根路径时要显示的文件或者Servlet,这个元素一般包含一到多个welcome-file,welcome-file的值可以是文件或者Servlet url-pattern。假如找不到第一个welcome-file指定的文件或Servlet,那么容器将尝试找第二个welcome-file,以此类推。
监听器加载顺序
如果是实现了同一个监听器接口的监听器,那么加载顺序是根据listener元素在web.xml中的顺序。
过滤器匹配规则
1.一个请求可以被多个过滤器捕获。
2.如果一个请求被多个过滤器捕获,那么处理顺序和和filter-mapping在web.xml中的顺序有关。FilterChain#doFilter方法调用前的代码是根据filter-mapping在web.xml中的顺序,FilterChain#doFilter方法调用后的代码是和filter-mapping在web.xml中的顺序相反。
Servlet匹配规则
1.如果请求已经被某个Servlet捕获,那么不会再被其他Servlet捕获。
2.多个Servlet如果设置一样的url-pattern,经过测试,最后配置的servlet-mapping将会生效。
3.匹配顺序,优先级从高到低是精确路径匹配 -> 目录匹配 ->扩展名匹配 ->默认匹配。精确路径匹配就像url-pattern是/a/b,servlet path也是/a/b这样的。目录匹配中有个要注意的,如果多个url-pattern都匹配时,最终会匹配url-pattern最长的那个Servlet,例如url-pattern有/test/a/*和/test/*,servlet path是/test/a,那么会匹配/test/a/*。
安全认证
<!--用于安全约束中的安全角色的声明,需要存在于特定服务器文件如tomcat-users.xml-->
<security-role>
<description>安全认证角色</description>
<role-name>auth</role-name>
</security-role>
<!--security-constraint元素是用来指示服务器使用何种验证方法了。此元素在web.xml中应该出现在login-config的紧前面。
它包含了:web-resource-collection、auth-constraint、user-data-constraint和display-name-->
<security-constraint>
<!--可选,描述信息的标签-->
<display-name>安全认证测试</display-name>
<!--此元素确定应该保护的资源。
所有security-constraint元素必须包含至少一个web-resource-collection-->
<web-resource-collection>
<!--受保护资源标识名称-->
<web-resource-name>资源名称</web-resource-name>
<!--受保护的URL,转发的请求不受保护-->
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.do</url-pattern>
<!--受保护的HTTP方法-->
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>HEAD</http-method>
<http-method>TRACE</http-method>
<http-method>POST</http-method>
<http-method>DELETE</http-method>
<http-method>OPTIONS</http-method>
</web-resource-collection>
<!-- 此元素指出哪些用户应该具有受保护资源的访问权。
包含一个或多个标识具有访问权限的用户类别role-name元素,以及包含(可选)一个描述角色的description元素-->
<auth-constraint>
<description>安全认证角色</description>
<role-name>auth</role-name>
</auth-constraint>
<!--用来显示怎样保护在客户端和Web容器之间传递的数据
NONE,对所用的通讯协议不加限制
INTEGRAL,数据必须以一种防止截取它的人阅读它的方式传送
CONFIDENTIAL,这意味着传输的数据必须是加密的数据
虽然原理上(并且在未来的HTTP版本中),INTEGRAL和CONFIDENTIAL之间可能会有差别,但在当前实践中都只是要求SSL-->
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!--HTTP有有四种认证方式,客户端证书验证暂时略过-->
<!--<login-config>-->
<!--<!–基本认证–>-->
<!--<auth-method>BASIC</auth-method>-->
<!--<!–代表请求认证响应头WWW-Authenticate realm的值–>-->
<!--<realm-name>BASIC AUTH</realm-name>-->
<!--</login-config>-->
<!--<login-config>-->
<!--<!–DIGEST认证–>-->
<!--<auth-method>DIGEST</auth-method>-->
<!--<!–代表请求认证响应头WWW-Authenticate realm的值–>-->
<!--<realm-name>DIGEST AUTH</realm-name>-->
<!--</login-config>-->
<login-config>
<!--表单认证-->
<auth-method>FORM</auth-method>
<form-login-config>
<!--登录页面-->
<form-login-page>/login.html</form-login-page>
<!--登录失败页面-->
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>