在介绍Spring IoC和MVC的加载前,用这篇小文章简单地记录下,最简单的web应用的加载过程。

一、从最简单的web应用出发

使用Eclipse直接创建一个Dynamic Web Project即可,工程如下test-web,然后右键→Run as→Run on Server,然后访问:http://localhost:8080/test-web/

可以看到,返回的是404错误,表示找不到请求的资源。

其实这个web应用是可运行而且没问题的。问题在于它没有Servlet可以接收并处理请求,在这里也没有定义首页和错误页的默认选项,因此应用直接返回了404找不到资源错误。如果把首页配置上去,默认的访问可以直接使用首页,我们增加web.xml和欢迎页index.jsp,如下

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>test-web</display-name>
<welcome-file-list>
<welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
</welcome-file-list>
</web-app>

index.jsp

 <%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>Hello
</body>
</html>

重新启动应用,然后访问http://localhost:8080/test-web/,结果如下。

可见,确实得到了正确的响应。

二、Web应用的简单加载过程

那Web是怎样加载的呢?如下图:

简单地说,web应用加载后,会先初始化整个web应用的唯一的ServletContext,即Servlet应用上下文(说白了就只有这一步)。这个上下文是必须要有的,而且每个web应用只有一个。ServletContext定义了运行在Servlet的应用程序环境的一些行为和观点,可以使用ServletContext实现对象来取得所请求资源的URL、设置与存储属性、应用程序初始参数,甚至动态设置Servlet实例。web.xml中配置的首页、错误页等,都会被web应用解析并按照最后的请求适配处理。

ServletContext属性的配置可以在web.xml的<context-param />中配置:

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

       总结一句话就是:web应用在部署时,web容器为web应用初始化了唯一的ServletContext,之后其他的可扩展选项按照配置进行初始化,然后就开始接收请求进行处理。

以上便是一个最简web应用的加载。

三、Web应用的常规加载过程

实际上,一个web.xml里面有很多的配置,而其中,接触最多的就是Listener、Filter、Servlet。在这里。我们并没有定义Listener、Filter、Servlet(实际处理请求的类),这是可行的,因为这些都是可扩展的选择。下面简单地介绍下这几个扩展选项:

1、Listener:

Web容器管理Servlet/JSP相关的对象生命周期,若对HttpServletRequest对象、HttpSession对象、ServletContext对象在生成、销毁或相关属性设置发生变化的时机点有兴趣,需要进行一些处理,如进行资源的加载、数据库的初始化等,可以使用Listener。主要有2大类的监听器Listener:

  1. ServletContext事件监听器:ServletContextListener、ServletContextAttributeListener
  2. HttpSession事件监听器:HttpSessionListener、HttpSessionAttributeListener、HttpSessionBindingListener、HttpSessionActivationListener

下面主要讲解ServletContext相关的2个监听器,其作用如下:

Spring IoC容器的配置就是ServletContextListener的实现类ContextLoaderListener,它在ServletContext加载之后就开始进行IoC容器的初始化和bean的加载解析。配置如下:

     <!-- 默认的spring配置文件是在WEB-INF下的applicationContext.xml -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext*.xml
</param-value>
</context-param>

2、Filter

在容器调用Servlet的service()方法前,Servlet并不会知道有请求的到来,而在Servlet的service()方法运行后,容器真正对浏览器进行HTTP相应之前,浏览器也不会知道Servlet真正的响应是什么。过滤器Filter正如其名称所示,是介于Servlet之前,可拦截过滤浏览器对Servlet的请求,也可以改变Servlet对浏览器的响应。Filter的解析是按照其在web.xml中的声明顺序来的。

常见到的就是强制字符转码的CharacterEncodingFilter:

     <filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

3、Servlet

这是处理实际请求的类,整个web应用存在的意义,是因为存在可以处理实际请求的Servlet,因此,一般Web应用中都需要配置Servlet。而Spring Web MVC中配置的类就是DispatcherServlet,如下:

     <!-- springMVC的核心控制器 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

从以上定义可以看出(实际上也可以进行调试debug):这些加载顺序  context-param  ==>  Listener  ==>  Filter  ==>  Servlet。

大体的加载流程表示如下:

  1. 读取web.xml的配置参数,如context-param、listener配置等
  2. web容器为web应用初始化一个唯一的全局上下文ServletContext,并把上述的参数配置即context-param,维护到ServletContext中。
  3. ServletContext初始化完成后,初始化配置的Listener,这里是Spring的ContextLoaderListener(实现了ServletContextListener,ServletContext初始化完成后会调用其contextInitialized方法),初始化Spring的IoC容器,即ApplicationContext,同时把自己设置给ServletContext,并设置WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE。
  4. 按照顺序加载配置Filter
  5. 加载配置的Servlet。这里是DispatcherServlet,它会初始化自己的ApplicationContext(主要是controller),同时把IoC容器的ApplicationContext,即WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE设置为自己的父容器,并注册在ServletContext。

整体的web.xml配置

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0"> <!-- 默认的spring配置文件是在WEB-INF下的applicationContext.xml -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext*.xml
</param-value>
</context-param> <!-- 强制进行转码 -->
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- springMVC的核心控制器 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- session配置 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config> <!-- 欢迎页面 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <!-- 错误页面 -->
<error-page>
<error-code>403</error-code>
<location>/WEB-INF/jsp/403.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/jsp/500.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
</web-app>

备注:web.xml的其他配置、IoC的记载、DispatcherServlet的解析等后续将进行逐一介绍。

Java Web应用的加载过程的更多相关文章

  1. web.xml的加载过程配置详解

      一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...

  2. web.xml 的加载过程

    初始化过程: 在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>. 接着容器会创建一个Serv ...

  3. web.xml的加载过程是context-param >> listener >> fileter >> servlet

    web.xml的加载过程是context-param >> listener  >> fileter  >> servlet

  4. Java web 项目 web.xml 配置文件加载过程

    转载自:http://blog.csdn.net/luoliehe/article/details/46884757#comments WEB加载web.xml初始化过程: 在启动Web项目时,容器( ...

  5. java web项目启动加载顺序

    转载:https://www.cnblogs.com/writeLessDoMore/p/6935524.html web.xml加载过程(步骤):       1.启动WEB项目的时候,容器(如:T ...

  6. java web程序启动加载 ContextLoaderListener

    浅析ContextLoaderListener 大家可能对下面这段代码再熟悉不过了 <context-param> <param-name>contextConfigLocat ...

  7. java web eclipse中项目的加载过程

    java web eclipse中项目的加载过程: Tomcat默认从WEB-INF/目录下加载资源,Eclipse在发布程序的时候,并没有把User Libraries的相关资源拷贝到WEB-INF ...

  8. Java web 加载过程

    1.Web容器初始化过程 2.SpringMVC中web.xml配置 3.认识ServletContextListener 4.认识ContextLoaderListener 5.Dispatcher ...

  9. java web.xml被文件加载过程及加载顺序小结

    web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...

随机推荐

  1. 010、Java中扩大数据类型

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  2. uniapp 小程序 flex布局 v-for 4栏展示

    注:本项目的图片资源来源于后端接口,所以使用的是v-for. 关键词:uniapp 小程序 flex布局 v-for 4栏展示 自适应 <view style="display: fl ...

  3. mysql limit查询入门

  4. Oracle 中启用 scott 用户 的方法

    解锁scott: SQL> alter user scott account unlock 修改密码: SQL> alter user scott identified by tiger ...

  5. Linux下Tomcat带日志启动命令

    在Linux环境下,启动Tomcat时我们需要在启动过程中看到日志信息.可以通过下面命令启动Tocmat. ./startup.sh; tailf ../logs/catalina.out或者 ./s ...

  6. POJ1723 SOLDIERS 兄弟连

    SOLDIERS 有一个性质:在一个长为n的序列a中找一个数 \(a_k\) 使得 \(\sum\limits_{i=1}^n abs(a_i-a_k)\) 最小,则 \(a_k\) 是a的中位数. ...

  7. P 1038 统计同成绩学生

    转跳点:

  8. UVA - 816 Abbott's Revenge(bfs)

    题意:迷宫从起点走到终点,进入某点的朝向不同,可以出去的方向也不同,输出最短路. 分析:因为朝向决定接下来在该点可以往哪里走,所以每个点需要有三个信息:x,y,d(坐标和进入该点的朝向),所以将起点的 ...

  9. JPA#复杂查询#引子

    _ 震惊....简历上写精通JPA的被下面几个问题震呆了.... 几个问题: 复杂查询如何从前端传递到后端,特别是多个条件的.且具有and和or等复杂逻辑,这个要如何封装呢? 多表查询? 自定义sql ...

  10. tornado5.0+async+await

    不使用数据库的情况下实现异步 使用gen.sleep()模拟阻塞 使用gen.sleep(time) 而不是time.sleep(),time.sleep()阻塞整个进程,看gen.sleep()源码 ...