前面的章节讲述了Servlet和Filter,不说一下web.xml总感觉少点什么。
好多人都知道web项目要配置web.xml,没有web.xml,web工程就起不来,为什么呢?我跟大部分一样都从未静下心来去细细品味一下。、
web.xml,中文名为部署描述文件,该文件由servlet定义,是web应用的配置文件。
部署描述符文件和其他的XML文件一样,都要由一个XML头开始。
这个头需要声明使用的XML版本,以及该xml使用的字符编码。
DOCYTPE声明可以有,也可以没有,本人使用的maven创建的web工程中,web.xml中没有该部分。
而创建的html文件中则有该部分的声明,例如:<!doctype html>,只是声明该文档是个html。
在这个声明之后,需要指定管理此文件其余部分内容的语法的DTD(Document Type Definition,文档类型定义),该语法会识别你的web.xml填写的是否正确。
在web.xml中其顶层元素为web-app,web.XML元素不像HTML,他们大小写敏感。
下面用maven创建web工程的web.xml代码(web.xml中的成员暂不填写):
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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程序启动时,web容器(tomcat等)就会去读取web.xml文件。
有人会问为什么叫web.xml,不叫其它的,这个我是没办法解释的,例如猫为什么叫猫....谁知道呢?
至于web容器(tomcat之类)怎么去读取的web.xml,这个我还是能大概说一下。
当tomcat启动的时候,tomcat会获取Catalina等其他类的一些数据,并设置一些参数,这些参数供tomcat使用。
当我们将我们的web应用部署在tomcat上时,tomcat就会读取我们web.xml,读取web.xml的代码如下(截取一部分):
protected void webConfig() { ...... WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(), context.getXmlValidation(), context.getXmlBlockExternal()); Set<WebXml> defaults = new HashSet<>(); defaults.add(getDefaultWebXmlFragment(webXmlParser)); WebXml webXml = createWebXml(); // Parse context level web.xml InputSource contextWebXml = getContextWebXmlSource(); // 读取/WEB-INF/web.xml if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) { // /WEB-INF/web.xml文件的内容解析到webXml里面 ok = false; } ServletContext sContext = context.getServletContext(); Map<String,WebXml> fragments = processJarsForWebFragments(webXml, webXmlParser); // 解析的是webFragment ...... // Step 3. Look for ServletContainerInitializer implementations if (ok) { processServletContainerInitializers(); // 这个是解析继承ServletContainerInitializer类的配置, } ...... }上面的代码设定了去哪个路径下读取web.xml并解析,以及获取servletContext等。
由此可知web.xml为什么在web-INF目录下,tomcat是怎么读取web.xml的都进行了简单描述。
我不想讲太多,在这里我想说的是,你不需要深入了解这一块,但是要知道红色线标记的这一块。
如果你想学习更多的,请深入学习一下tomcat,当然也可以参考下面这个大神的博客。
http://blog.csdn.net/x87648510/article/details/51750550
大概说了web容器加载web.xml的过程,接下要说一下web.xml中常用到的成员。
1.schema
web.xml的模式文件是由Sun公司定义的,每个web.xml文件的根元素<web-app>中,都必须标明这个 web.xml使用的是哪个模式文件。
其它的元素都放在<web-app></web-app>之中。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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>
2.<display-name>,Web应用的名称,用来标记这个特定的Web应用的一个名称
<display-name>Tomcat Example</display-name>
3.<context-param>,web应用上下文参数,声明应用范围内的初始化参数。
它用于向 ServletContext提供键值对,即应用程序上下文信息。我们的listener, filter等在初始化时会用到这些上下文中的信息。
在servlet里面可以通过getServletContext().getInitParameter("context/param")得到。
<context-param> <param-name>ContextParameter</para-name> <param-value>test</param-value> </context-param>
4.<filter>过滤器,将自写的Filter过滤类,添加到web应用中,这个过滤类需要实现javaxs.servlet.Filter接口(具体可以看我前面的章节)
<filter> <filter-name>setCharacterEncoding</filter-name> <filter-class>com.abc.FilterA</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>setCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>5.<listener>监听器
<listener> <listerner-class>com.listener.SessionListener</listener-class> </listener>
6.<servlet>, 用来声明一个servlet的数据
<servlet-name></servlet-name> 指定servlet的名称
<servlet-class></servlet-class> 指定servlet的类名称
<jsp-file></jsp-file> 指定web站台中的某个JSP网页的完整路径
<init-param></init-param> 用来定义参数,可有多个init-param。在servlet类中通过getInitParamenter(String name)方法访问初始化参数
<load-on-startup></load-on-startup>指定当Web应用启动时,装载Servlet的次序。
当值为正数或零时:Servlet容器先加载数值小的servlet,再依次加载其他数值大的servlet。
当值为负或未定义:Servlet容器将在Web客户首次访问这个servlet时加载它。
<servlet-mapping></servlet-mapping> 用来定义servlet所对应的URL,包含两个子元素
<servlet-name></servlet-name> 指定servlet的名称
<url-pattern></url-pattern> 指定servlet所对应的URL
<!-- 基本配置 --> <servlet> <servlet-name>snoop</servlet-name> <servlet-class>SnoopServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>snoop</servlet-name> <url-pattern>/snoop</url-pattern> </servlet-mapping> <!-- 高级配置 --> <servlet> <servlet-name>snoop</servlet-name> <servlet-class>SnoopServlet</servlet-class> <init-param> <param-name>foo</param-name> <param-value>bar</param-value> </init-param> <run-as> <description>Security role for anonymous access</description> <role-name>tomcat</role-name> </run-as> </servlet> <servlet-mapping> <servlet-name>snoop</servlet-name> <url-pattern>/snoop</url-pattern> </servlet-mapping>
7.<session-config>会话超时配置,单位为分钟
<session-config> <session-timeout>120</session-timeout> </session-config>8.<welcome-file-list>欢迎文件页
<welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> </welcome-file-list>
9.<error-page>错误页面
<!-- 1、通过错误码来配置error-page。当系统发生×××错误时,跳转到错误处理页面。 --> <error-page> <error-code>404</error-code> <location>/NotFound.jsp</location> </error-page> <!-- 2、通过异常的类型配置error-page。当系统发生java.lang.NullException(即空指针异常)时,跳转到错误处理页面。 --> <error-page> <exception-type>java.lang.NullException</exception-type> <location>/error.jsp</location> </error-page>
web.xml中的常用的基本成员都在上面了。
虽然大多数人已经学习了SSH,不看这一些东西,但是这些东西是真正的基础,搞不懂这些,SSH也就难以更上一层楼。
叙述过了Filter和Listener,也说过了Servlet,那就说一下web容器加载web.xml中成员的顺序:
web容器加载web项目时,会去读取web.xml。在web.xml中,他会读取listener,Filter,Context-param。
读取顺序:首先会读取context-param,再读取listener,读取完这两个,就会去创建ServletContext。
(在listener中,我曾说过,实现指定接口后的监听类可以监听application,即ServletContext。如果不读取Listener,那就没办法创建监听,即接下来对application的相关操作无从得知)
监听读取过了,被监听对象的参数也有了。现在创建被监听对象ServletContext。(被监听对象由web容器创建),然后容器将被监听对象的参数传给监听对象(Context-param传给ServletContext),接下来创建监听对象(listener),在实现的监听对象中,我们可以通过监听对象获得已经创建的ServletContext,以及Context-param参数。
因为ServletContext是当前web项目共享的,所以它比所有的servlet创建的都要早,既然ServletContext比Servlet的创建早,那么对Context-param做相关操作也必然比servlet的创建要早。
由此得知:web.xml中会先读取Context-param,然后是listener,再读取Filter。
Filter因为可以过滤用户对某个Servlet的请求,所以,应该在创建Servlet前被创建。
由此,我们得知:context-param -> listener -> filter -> servlet
另外,web.xml中的成员顺序不影响web容器对其的读取顺序,毕竟取值的时候按key-value读取的。