小白新手web开发简单总结(二)-什么是web.xml

目录

一 什么是web.xml

二 web.xml配置项

1.web-app

 2.context-param 和listener

(1)context-param

(2)listener

(3)context-param和listener  应用场景

3.filter和filter-mapping

4.servlet和servlet-mapping

5.其他配置项

扫描二维码关注公众号,回复: 12775979 查看本文章

(1)session-config

(2) mime-mapping

(3)welcome-file-list

(4)error-page

三 总结


一 什么是web.xml

在上一篇在上面一小白新手web开发简单总结(一)-什么是Tomcat在介绍Context的时候提到,在每个web应用的工程下有一个webapp的目录,在该目录下通常会按照模块进行划分成不同的文件夹来存放JSP文件和资源文件,每个文件夹都是一个Context。

在webapp目录下,必定会有一个WEB-INF的目录,在该目录下有一个web.xml文件。这个web.xml文件为web应用的配置文件,用来配置web应用的欢迎页、servlet、filter、listener等。

当然这个web.xml文件并不是必须的,如果项目中没有用到这些配置内容,则可以不去配置web.xml。最后将web应用打包到服务器供用户访问的时候,WEB-INF的目录用户是无法访问的。

当启动一个web应用的时候,web容器(像JBoss、Tomcat等)就会读取web.xml里面的配置项,完成实例化配置项内容,只有该步骤没有出错,项目才能正常启动。下面主要分析下web.xml的各个配置项

二 web.xml配置项

1.web-app

根元素。必须标明web.xml使用的是哪个文件。

<web-app version="3.1"
	xmlns="http://java.sun.com/xml/ns/j2ee"   
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">    
.......
</web-app>

我觉得这个应该就和Android中的这种命名空间,用前面的xsi来代替后面的那个链接。最终这个标明了xml schema的位置。

xmlns:android="http://schemas.android.com/apk/res/android"

 2.context-param 和listener

在启动web应用的时候,web容器(例如Tomcat)首先会读取web.xml的<context-param>和<listener>,完成两件事情:

(1)context-param

  • 1)将<context-param>转换成key-value存放到ServletContext中;

<context-param>主要存放的是ServletContext的初始化参数以及JSP的application内置对象读取的初始化参数。

ServletContext又被成为Servlet上下文。web容器(例如Tomcat)会为每个应用程序创建一个ServletContext对象。该对象是全局唯一,而且所有的Servlet都共用这一个对象。该对象包含了所有的Servlet共用的资源信息,通过一组方法来供Servlet使用,可以在不同的Servlet之间传递数据,比如获取文件的MIME类型、分发请求、记录日志等。如果该web应用是分布式部署,那么每台服务器上部署的web应用实例都拥有一个Servlet实例。可以通过getServletContext()来获取到ServletContext实例。当然一个web服务器上也可以部署多个web应用,那么web服务器也会为每一个web应用创建全局唯一的ServletContext。

那么getServletContext()最终就是保存到ServletContext中,供不同的Servlet来使用,所以<context-param>里面的内容可以被所有的Servlet通过ServletContext调用到,并不属于任何一个Servlet。在项目中可以通过 getServletContext().getInitParameter(“param-name”)(其中name为<context-param>配置的<param-name>)获取到对应的值。 

而这个JSP的application其实就是ServletContext,只不过在JSP中叫application,在Servlet中叫ServletContext。主要就是通过这两个类分别放在JSP和Servlet中共享数据。所以在<context-param>中配置的内容在两者都可以读到,同时在任何一边通过setAttribute()修改的值,在两边都可以读取到对应的内容。

在一个web服务器中,会提供四个类似Map的结构:application、session、request、page,并且运行JSP和Servlet对这四个结构值进行修改,只不过这四个类的作用范围不一样:

application:对整个web应用都有用,该应用下的所有JSP、Servlet都可以访问到里面的值;

session:仅对一次会话有效,只针对该次会话中的JSP、Servlet可以访问到里面的值;

request:仅对本次请求有效,只能被该次请求的JSP、Servlet访问;

page:仅对当前页面有效,只能针对当前页面的JSP、Servlet访问。

<context-param>并不是项目中必须要配置的。

举个例子来说明<context-param>的使用:在一个非Spring MVC架构的项目中,通常使用applicationcontext.xml(主要放置的是一些与业务逻辑有关的bean)来加载Application Context,那么就需要配置contextConfigLocation。

如果不在web.xml配置contextConfigLocation,那么当web容器启动之后,就会默认的去/WEB-INF/applicationcontext.xml文件找。但是如果自定义了配置文件的文件名的话,就需要通过contextConfigLocation来配置该文件,如下

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:config/application-context-*.xml</param-value>
</context-param>

其中 classpath:只会到该路径下中查找文件;classpath*:不仅包含class路径,还包含jar中(class路径)进行查找。

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

通常在配置<servlet>进行的时候也会通过<init-param>配置contextConfigLocation,这两个的区别在后面介绍到<servlet>,在具体总结下。

当在<context-param>配置了contextConfigLocation,通常还会在web.xml中添加<listener>。这也就是在web容器启动的时候,在完成第一步读取<context-param>的内容之后,再将<listener>中对应的类实例进行实例化。

(2)listener

  • 2)将<listener>中配置的类实例,按照配置的路径进行实例化监听相关事件。

这些类实例可以是自定义的监听类,但必须根据具体事件的监听来实现系统接口。现在先拿ServletContextListener来举例说明,在这接口中有两个方法:


public interface ServletContextListener extends EventListener {
    void contextInitialized(ServletContextEvent var1);

    void contextDestroyed(ServletContextEvent var1);
}

很明显的可以看出,web容器在创建<listener>对应的类实例,首先会调用到contextInitialized(ServletContextEvent var1)来初始化完成初始化工作,当然在这个方法中可以通过var1.getServletContext().getInitParameter("name")(其中name为<context-param>配置的<param-name>)来获取到<context-param>配置的值,在web项目启动之前,完成一些初始化的工作;当然在web应用关闭的时候,也会调用到该监听类的contextDestroyed(ServletContextEvent var1)方法来完成释放一些资源等工作。

举个例子来说明下这个<listener>的使用:在配置一个Spring项目时,必须配置<listener>。通常需要在项目中增加ContextLoaderListener这个监听来自动加载ApplicationContext配置的信息,一般会与<context-param>搭配使用(通过contextConfigLocation配置ApplicationContext),但是<context-param>不是必须的。

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

该ContextLoaderListener的作用就是在启动web容器的时候,读取在contextConfigLocation配置的xml文件(也就是通过<context-param>配置的初始化参数),自动装配ApplicationContext的配置信息,并产生一个WebApplicationContext对象,同时将ServletContext 绑定到 WebApplicationContext,也将WebApplicationContext绑定到ServletContext。这样就可以利用WebApplicationContext对象来访问容器管理的bean(这里就产生一个自己需要后面继续学习的问题:在一个项目中我怎么知道需要加载哪些bean呢?这些bean应该是一些与业务逻辑相关的bean)

ApplicationContext是加载applicationcontext.xml文件为整个应用创建的ApplicationContext,加载配置文件中的bean,将所有的bean集中起来。

WebApplicationContext继承于ApplicationContext接口,增加了Web应用的特性,可以视图解析、主题解析、映射、通过ServletContext和Servlet关联,在ContextLoaderListener中将WebApplicationContext 绑定到中ServletContext(servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);)

常见的web监听事件接口如下: 

 ServletContextListener:用于监听web应用的启动和关闭(包括Initialized/Destroyed事件)

ServletContextAttributeListener:用于监听ServletContext范围内的属性的改变(包括Add/Remove/Replace事件)

ServletRequestListener:用于监听用户请求(包括Initialized/Destroyed事件)

ServletRequestAttributeListener:用于监听ServletRequest范围内的属性的改变(包括Add/Remove/Replace事件)

HttpSessionListener:用于监听用户session的 创建和结束(包括Created/Destroyed事件)

HttpSessionAttributeListener:用于监听用户session的范围内的属性的改变(包括Add/Remove/Replace事件)

(3)context-param和listener  应用场景

针对这两个配置项可以应用的一个场景举例:在web项目启动之前,需要打开数据库

那么针对这个实现需要有两步:

(1)通过<context-param >配置数据库的一些基本信息,像url、user、password等

(2)自定义监听类来实现ServletContextListener接口:在contextInitialized(ServletContextEvent var1)读取到<context-param >配置的内容打开数据库;在contextDestroyed(ServletContextEvent var1)释放资源,关闭数据库等。

到目前为止,此时web应用还没有启动完成。

3.filter和filter-mapping

在web应用在启动之前,完成读取<context-param>和<listener>工作之后, 其次读取<filter>的内容,根据指定的类路径来完成实例化过滤器。

filter的工作主要是用来对用户请求request进行预处理,对response进行后加工。在客户端发送过一个请求的时候,filter首先会对该请求进行预处理,然后才会将该请求封装为SerlvetRequest转交给Servlet进行处理并响应,Servlet响应完的ServletResponse交给filter进行后处理之后,在返回给客户端。

根据不同的应用场合,有不同的功能的filter:认证filter、日志和审核filter、图片转换filter、数据压缩filter、密码filter、令牌filter、触发资源访问事件的filter、性能监控 filter、媒体类型链filter等(当然一些公共功能的处理都会放到Filter中)。

自定义的Filter都需要实现javax.sevlet.Filter接口。该接口中的实现过滤功能的核心方法doFilter(ServletRequest request,ServletResponse response,FilteChain chain),用来对请求和响应增加过滤功能。

在web.xml中通过.<filter>来进行定义filter。通常与<filter-mapping>配合使用,<filter-mapping>用来告诉将哪些请求或响应交给该filter来处理,两个的<filter-name>必须一致。

举例一个比较常用的字符集转换的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>

<url-pattern>*</url-pattern>使用通配符*,说明所有的请求都会先被该过滤器拦截,按照指定的utf-8进行编码之后,在进行向下转发。

经过了前面三个,此时一个web项目已经启动成功。

4.servlet和servlet-mapping

在前一篇小白新手web开发简单总结(一)-什么是Tomcat也提到了Servlet,主要用于来处理业务逻辑,Servlet被初始化之后,会一直存在Servlet容器中,通常仅在关闭web应用的时候才销毁Servlet。由Servlet容器调用Servlet的doGet()/doPost()进行处理并响应请求,或者统一使用service()来响应请求。Servlet容器在销毁Servlet的时候,会调用到Servlet的destroy()。如果能让Servlet响应用户的请求,那必须将Serlvet配置到web应用中。

通常在项目中可以通过两种方式来配置Servlet:

  • (1)一种就是在Serlvet类中通过@WebServlet Annotation进行配置;
  • (2)另外一种就是在web.xml中通过<servlet><servlet-mapping>和来进行配置。

一般来说<servlet>是在第一次发起请求的时候才被实例化的,而且一般不会被Serlvet容器销毁,可以服务于多个用户的请求。

所以综上前四个的加载顺序为<context-param> -> <listener> -> <filter> -> <servlet>。

但是<servlet>也可以通过配置<load-on-startup>在web应用启动的时候立即创建Servlet实例。通过一个实例来说明这个<servlet>:在配置Spring MVC时,通常会配置Spring MVC的前端控制器,用来拦截请求(我现在理解的目前项目之所以有Tomcat、Spring MVC以及SOA服务,那么这个DispatcherServlet就是将Spring MVC本来交给Controller的请求给拦截,然后交给Tomcat的Servlet来处理,不知道我的这种理解是不是正确的。。。)

	<servlet>
<!--定义Servlet的名字,全局唯一,和"<servlet-mapping>"中的保一致-->
		<servlet-name>SpringMvc</servlet-name>
<!--指定Servlet类-->
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化参数-->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:config/spring-mvc.xml</param-value>
		</init-param>
<!--该Serlvet载入容器的顺序-->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringMvc</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>

<servlet>用来配置Servlet,必须含有<servlet-name>和<servlet-class>或者<servlet-name>和<jsp-file>。

  • <serlvet-name>定义了Servlet的名字,该名字必须在整个web应用中具有唯一性。 
  • <serlvet-class>指定Serlvet类;如果不指定<serlvet-class>,也可指定<jsp-file>。当指定<jsp-file>时,并且还设置了<load-on-startup>,那么JSP文件也会被编译成Servlet,放到内存中。
  • <load-on-startup>用来指定Servlet载入的容器的顺序:
  • 如果<load-on-startup>该值为空或者为负值的时候,有Servlet容器决定先载入哪个Serlvet;
  • 如果<load-on-startup>值为1,表示在web应用启动的时候,就加载该Serlvet,但是加载顺序还是排在<context-param> -> <listener> -> <filter>之后;
  • 如果<load-on-startup>的值为正数的时候,值越小,Servlet越被优先加载。
  • <init-param>初始化参数,和<context-param>的用法一致。只不过<context-param>是对所有的Serlvet和JSP的application有效,而<init-param>只针对当前Servlet有效。在当前Serlvet中通过getServletConfig().getInitParameter(“name”)(其中name为<context-param>配置的<param-name>)来获取到对应到配置值。在配置Spring MVC时,默认的读取会在/WEB-INF/SpringMvc-servlet-xml(该文件的命名方式为:[servlet-name]-servlet.xml)配置文件,当然也可以通过在<init-param>设置contextConfigLocation来指定MVC的配置文件。那这里我就有了一个自己的疑问,像这个SpringMVC的配置文件到底需要配置哪些内容???就和applicationcontext.xml这个文件里面的内容感觉都还不是很清楚到底配置了什么????但是我现在理解的应该是:每一部分都会有一个配置文件)

<servlet-mapping>用来配置Servlet的访问路径。

  • <serlvet-name>该值必须与<servlet>的<serlvet-name>一致
  • <url-pattern>用来指定该Servlet处理的URL。当容器的Context对象对请求的URL进行处理之后,按照路径的映射规则和Servlet的映射规则(就是<url-pattern>配置的规则)做匹配,如果恰好符合该规则,则该请求交给该Servlet进行处理。

(这个我觉得后面还需要再继续想想到底ContextLoaderListener和DispatcherServlet是怎么配合的?一个Spring MVC需要配置什么?项目中的Tomcat、Spring MVC、SOA之间的关系到底是什么???)

我们也可以在项目中配置其他的Servlet来分别处理不同的请求。

像<filter>、<servlet>等同一个配置项,在一个web.xml中可以配置多个,那么当同一个配置项配置多个,那么在启用的时候,是怎么按照什么顺序依次实例化呢?举例<filter>:<filter>与<filter-mapping>搭配出现,对于有相同<filter-name>的<filter>与<filter-mapping>配置项而言,<filter-mapping>必须出现在<filter>的后面。当web容器在初始化这些<filter>的时候,会按照在web.xml出现的顺序依次进行初始化。当客户端发送的请求中匹配多个<filter>的时候,也会按照<<filter-mapping>出现的顺序依次调用对应的doFilter()方法。

5.其他配置项

剩下的配置项应该就属于一些比较好理解的配置项了。所有的配置项可参照官方文档https://docs.oracle.com/cd/E11035_01/wls100/webapp/web_xml.html#wp1070143

(1)session-config

设置web容器的session参数,比如<session-timeout>用于指定http session失效的事件,默认单位为min。如果设置为0或者负数,则表示永不失效。

	<session-config>
<!--时间单位:分钟 -->
		<session-timeout>30</session-timeout>
	</session-config>

(2) mime-mapping

指定浏览器可以打开的文件类型

 <mime-mapping> 
     <extension>doc</extension>
     <mime-type>application/msword</mime-type> 
 </mime-mapping> 
 <mime-mapping> 
      <extension>xls</extension> 
      <mime-type>application/msexcel</mime-type> 
  </mime-mapping> 
  <mime-mapping> 
      <extension>pdf</extension> 
      <mime-type>application/pdf</mime-type> 
  </mime-mapping>
  <mime-mapping> 
      <extension>zip</extension> 
      <mime-type>application/zip</mime-type> 
  </mime-mapping>
  <mime-mapping> 
      <extension>rar</extension> 
      <mime-type>application/rar</mime-type> 
  </mime-mapping>
  <mime-mapping> 
      <extension>txt</extension> 
      <mime-type>application/txt</mime-type> 
  </mime-mapping>
  <mime-mapping>
      <extension>mp3</extension>
      <mime-type>audio/x-mpeg</mime-type>
  </mime-mapping>

(3)welcome-file-list

指定web应用的欢迎页。可以包含一个或多个<welcome-file>。会按照配置的顺序依次找到可以打开的文件。

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

(4)error-page

指定错误页面,可根据错误码和抛出的异常信息配置需要显示的页面

  <error-page>
      <error-code>404</error-code>
      <location>/jsp/common/404.html</location>
  </error-page>
  <error-page>
      <error-code>500</error-code>
      <location>/jsp/common/500.html</location>
  </error-page>
  <error-page>
      <exception-type>java.io.IOException</exception-type>
      <location>/jsp/common/IO.html</location>
  </error-page>

三 总结

大体梳理下目前现在已经理解的内容:

  • 1.一个web.xml配置项大体包括<context-param>、<listener>、<filter>和<filter-mapping>、<servlet>和<servlet>以及其他比较容易理解的配置项;
  • 2. web容器在加载web.xml配置项的时候,会按照<context-param> -> <listener> -> <filter>依次在web应用启动的时候进行实例化里面配置的内容;
  • 3.<context-param>配置的是初始化参数,针对整个web应用,将配置的内容转换成key-value的形式写入到ServletContext中。在Servlet通过ServletContext获取到配置项内容,在JSP中通过application获取到配置项的内容,这样就可以完成Serlvet之间以及servlet与JSP之间的数据共享;
  • 4.<param-name>contextConfigLocation</param-name>是用来配置配置文件的。在<context-param>中,则配置的是ApplicationContext的内容,针对的是整个web应用的bean,这些bean是一些业务逻辑bean的,在<init-param>,则配置的是针对Servlet的配置文件,仅在当前Servlet有效;
  • 5.通过在Spring MVC项目中通过在<listener>中配置ContextLoaderListener,通过该监听,当web应用启动的时候,配置ApplicationContext,并产生一个WebApplicationContext对象,并将WebApplicationContext写入到ServletContext,这样所有的Serlvet就可以都共享;
  • 6.<filter>主要就是对客户端产生的请求进行预处理,然后交给Servlet进行处理,并且对Servlet产生的响应在返回给客户端之前进行后处理;
  • 7.<servlet>的配置项,一般都是在客户端发送过请求之后,才会实例化Servlet,实例化的Servlet会一直存在,通过Servlet容器来管理Servlet进行处理请求;只有在web应用关闭的时候,才会将Serlvet进行销毁;
  • 8.在配置Spring MVC项目的时候,<servlet>通常会配置DispatcherServlet,通过<servlet-mapping>定义的规则匹配对应的请求,那么将这些符合匹配规则的请求交给了该Servlet进行处理;
  • 9.<servlet>可以通过配置<load-on-startup>来设置不同的Servlet的优先级,当然也可以通过该配置项来让在web应用启动的时候就去实例化Servlet;
  • 10.可以配置不同的<servlet>来按照不同的Servlet处理请求;
  • 11.一个web.xml是一个web应用的配置文件;通过在<context-param>配置contextConfigLocation是ApplicationContext的配置文件;通过在<servlet>中配置contextConfigLocation是Spring MVC的配置文件;
  • 12.同一个配置项允许有多个,当出现多个的时候,会按照配置顺序依次实例化,当在发挥作用的时候,也是按照之前实例化的顺序依次调用。
  • 13.<filter>、<servlet>就是定义对应的过滤器和Servlet,而<filter-mapping>、<servlet-mapping>就是设置匹配规则,当匹配对应的规则的时候,就交给Filter和Servlet来处理。

当然还有一些自己有疑问的地方需要在查找资料研究,当然也希望大佬给予指点。

  • 1.我觉得一个web.xml应该是一个web应用的入口,但是有的也提到可以不需要添加这个web.xml文件,那如果不添加这个web.xml文件,那一个工程又是怎么样呢?对一个web项目的一个简单的框架还是没有一个概念,需要在继续去了解。
  • 2.在第5条中产生的ApplicationContext和WebApplicationContext这两个对象具体是用来干什么的???
  • 3.针对第8条,自己产生一个疑问:Spring MVC本身不也是有Controller来实现业务逻辑,为什么要交给DispatcherServlet来处理?一个项目中的Tomcat、Spring MVC 以及SOA服务到底扮演了什么角色??(是不是可以理解为web应用是基于Spring MVC架构,本来请求是应该交给Controller,现在通过配置的DispatcherServlet将请求交给Tomcat的Serlvet来处理呢?SOA肯定是最底层提供服务的。如果是这样,好处是什么呢??web应用如果是Spring MVC不是本来有自己的M V 吗?)
  • 4.针对第10条,这些Servlet处理的请求,是浏览器分发过来的吗?这些请求为什么还需要使用不同的Servlet来处理?应用常见是什么呢??
  • 5.针对第11条的这些配置文件目前已经了解web.xml配置文件,那其他的配置文件到底应该包括哪些内容?为什么要有这些配置文件?如果要增加一个配置文件,该包括哪些内容呢??

加油,继续努力!!!!后面会分析一个简单的web应用开发,理解到底一个web应用开发应该包括哪些东西,见小白新手web开发简单总结(三)-一个简单的Spring项目

猜你喜欢

转载自blog.csdn.net/nihaomabmt/article/details/113523267