web.xml文件是我们开发Web程序的一项很重要的配置项,里面包含了我们各种各样的配置信息,比如欢迎页面,过滤器,监听器,启动加载级别等等。在服务器启动时,第一步便会加载项目的web.xml文件,然后通过其中的各种配置来启动项目,如果配置项都正确,则项目启动成功。
接下来我们以配置Spring MVC程序为例,来挨个看下web.xml中各项配置的含义。首先,我们来看一下web.xml文件最外层的web-app
标签:
<?xml version="1.0" encoding="UTF-8"?>
<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">
这是web.xml的头部声明,xmlns是命名空间的意思,其中的version是应用程序实现Servlet规范的版本,默认情况下,Java EE与Servlet版本对应关系如下:
Java EE | Servlet版本 |
---|---|
Java EE 8 XML schema | Servlet 4.0 |
Java EE 7 XML schema | Servlet 3.1 |
Java EE 6 XML schema | Servlet 3.0 |
Java EE 5 XML schema | Servlet 2.5 |
Java EE 1.4 XML schema | Servlet 2.4 |
再往前的版本就太老了,不用关注了。当然我们可以修改默认的version,但修改的时候记得注意对应schema的版本,不要出现兼容问题。
而xsi:schemaLocation
属性前面已经说过,该属性的使用格式为:xsi:schemaLocation="namespaceURI1 schemaURI1 namespaceURI2 schemaURI2 ..."
,这里是说使用schemaURI1所对应的schema文件,校验命名空间namespaceURI1下的元素是否符合XML语法规范,后面的则是以此类推。
icon标签,配置的是Web应用图标,指出IDE和GUI工具用来表示Web应用的大图标和小图标文件:
<icon>
<small-icon>/static/image/small.png</small-icon>
<large-icon>/static/image/big.png</large-icon>
</icon>
description标签是用于描述该web项目的功能,特性等。
<description>测试Spring MVC的项目</description>
该web项目的应用名称。
<display-name>SpringMVC-Test</display-name>
context-param标签是web.xml中用于配置应用于整个web项目的上下文,包含了三个参数。
description
描述信息;param-name
设定上下文的参数名称,是唯一的;param-value
设定参数名称的值,如果配置多个xml文件,使用逗号分隔,也可以使用如applicationContext-*.xml
类似的通配符。在Spring中配置如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
而在servlet中可以通过如下方式得到:getServletContext().getInitParameter("context/param")
。在web.xml中context-param
标签并不是必须存在的,如果不存在,则默认是contextConfigLocation
,而参数value则默认是/WEB-INF/applicationContext.xml
。
而在web.xml中,如果是配置spring,则必须要有listener标签。
listener标签是为web程序定义的监听器,用来监听各种事件,比如application和session事件,所有的监听器按照相同的方式定义,功能取决于它们各自实现的接口,常用的Web事件接口有如下几个:
配置Listener只要向Web应用注册Listener实现类即可,无序配置参数之类的东西,因为Listener获取的是Web应用ServletContext(application)的配置参数。配置如下:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在Spring3.0之前或许还有使用ContextLoaderServlet
来配置listener的,不过3.0版本之后已经删除了,目前只有通过ContextLoaderListener的方式来配置。
servlet标签配置的即是servlet,用于处理客户端过来的HTTP接口的请求及响应,<servlet>
标签和<servlet-mapping>
标签配套出现。我们拿Spring MVC的配置来看下:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
使用SpringMVC,首先要配置DispatcherServlet
,DispatcherServlet是前置控制器,用于拦截匹配的请求,然后根据我们配置的相应规则,分发到相应的Controller来处理。
servlet标签的属性大致如下:
- servlet-name:servlet的名称;
- servlet-class:servlet所对应类的名称,我们这里是DispatcherServlet;
- init-param:用于初始化传递给servlet的参数,类似于局部化的
context-param
节点,而访问的话通过ServletConfig
对象来完成,方法是getInitParamenter
。ServletConfig获取配置参数的方法和ServletContext获取配置参数的方法完全一样,只是ServletConfig是取得当前Servlet的配置参数,而ServletContext是获取整个Web应用的配置参数。
- 对于
init-param
节点下的param-value
,其实有多种写法;
a. 如果不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
;
b. 配置为:/WEB-INF/classes/dispatcher-servlet.xml
;
c. 配置为:classpath*:dispatcher-servlet.xml
;
d. 同样,多个值使用逗号进行分割;
- load-on-startup:启动顺序配置,也就是web应用程序加载该servlet的顺序,是一个整数。
Web容器加载servlet实例的时机一般分两种情况:
load-on-start Servlet
;如果该属性的值是正数或者0时,Web容器先加载数值小的,再加载数值大的;如果没有配置该属性,或该属性是负数时,Web容器将会在客户端首次访问到的时候才加载。
- servlet-mapping:用于指定servlet的URL的路径,包含两个参数:
servlet-name
,也就是我们上面配置的servlet的name,url-pattern
,该servlet对应的URL;
- 上面我们配置了SpringMVC的servlet,但我们的
url-pattern
处理的是所有的URL,如果我们要过滤掉一些静态文件,比如.jpg
,.js
等,我们就可以再写一个servlet来处理。其实,对静态文件的拦截有好几种方式,改天我们再仔细谈这个问题。
session-config,用于会话的超时配置,单位分钟;
<session-config>
<session-timeout>60</session-timeout>
</session-config>
filter是过滤器的意思,所谓的过滤,就是对请求未进入servlet之前进行预处理,或在请求结束返回给前端之间进行后处理的过程。filter和servlet有点像,配置都差不多,但也不太一样,根本原因就是servlet的目的是处理请求,而filter的目的是拦截和过滤请求。比如我们来看下编码过滤:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
比如我们配置了Spring的编码过滤器,可以解决我们项目中可能会出现的乱码问题。
用于指定Web应用程序的欢迎页面:
<welcome-file-list>
<welcome-file>/welcome.jsp</welcome-file>
</welcome-file-list>
用来配置错误情况下的跳转页面,有两种方式,一种是按照错误码来配置,另一种是按照异常类型来配置。
按照错误码来配置跳转页面,当系统发生404错误时,跳转至该页面:
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
按照异常类型来配置跳转页面,当系统出现空指针异常时,跳转至该页面:
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error/500.html</location>
</error-page>
服务器一般都具有一种让Web网站将文件扩展名与媒体相关联的方法。例如,将会自动给予名为mom.jpg的文件一个image/jpeg的 MIME 类型。但是,假如你的Web应用具有几个不寻常的文件,你希望保证它们在下载或发送给客户端时分配为某种MIME类型。而mime-mapping
标签正是用于这种用途,其中extension
属性表示扩展名,而mime-type
属性则为MIME类型。
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
比如有的时候我们可能会遇到这种情况,在浏览器下载doc文件,下载完成然后直接打开有时候会是乱码,下载后的文件类型可能不是doc类型。这种情况,我们就可以通过配置mime-mapping标签,将mime类型映射到扩展名,用于规定下载的格式,比如:
<mime-mapping>
<extension>ppt</extension>
<mime-type>application/vnd.ms-powerpoint</mime-type>
</mime-mapping>
<mime-mapping>
<extension>doc</extension>
<mime-type>application/vnd.ms-word</mime-type>
</mime-mapping>
目前常用的标签我们基本上都分析过了,剩下的基本上是不太常用的,等我们用到的时候再学习不迟。
web项目在启动的时候,会先加载web.xml的配置文件,来完成项目启动配置项的解析。所以接下来我们来了解下web.xml文件启动的时候的加载顺序。
- 容器在解析web.xml时,首先会去读取<context-param>`,提供应用程序上下文信息;
- 然后会加载
<listener>
节点,该节点会用到上下文的信息;- 然后会加载拦截器节点
<filter>
,如果有多个拦截器,则是按照拦截器配置的顺序来进行调用的;- 然后才会加载对应的
<servlet>
节点;
也就是说,web.xml中的加载顺序是:context-param
-> listener
-> filter
> servlet
;而同类型之间的加载顺序则是根据配置的顺序来进行加载的。所以我们配置的时候,需要注意下同类型标签的配置顺序;
其实,Spring到目前的最新版本5.0,而对应servlet的版本也已经到4.0了,功能已经特别强大了。早在许久之前,就支持servlet,listener,servlet等不必配置在web.xml中,并且可以完全做到零配置。因为Spring框架提供了类似WebApplicationInitializer
接口来完成web.xml中各项配置的注册等。
使用注解代替繁杂的XML配置,也遵循了约定优于配置
的思想,可以很大程度上提高我们的编程体验。目前很主流的Spring boot框架,基本上都是很少的配置,就可以开发一个完整的Spring MVC程序,等接下来有时间的时候我们再仔细来学习下Spring Boot。