在介绍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. mysql悲观锁处理赠品库存超卖的情况

    处理库存超卖的情况前,先了解下什么是乐观锁和悲观锁,下面的几篇博客已经介绍的比较详细了,我就不在赘述其原理了 [MySQL]悲观锁&乐观锁 对mysql乐观锁.悲观锁.共享锁.排它锁.行锁.表 ...

  2. 040、Java中逻辑运算之短路与运算“&&”

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

  3. excel表格数据导入导出

    /** * 导出数据到excel表格 * Created by shenjianhua on 2018-12-28 */ package com.luer.comm.excel; import jav ...

  4. Vulkan 之 Debugging

    1.可以用validation layers 进行验证: 2.Snapdragon Profiler 使用说明

  5. 133-PHP子类无法重写父类private同名函数

    <?php class father{ //定义father类 //定义protected成员方法 protected function cook(){ return 'protected co ...

  6. 移动端触屏click点击事件延迟问题,以及tap的解决方案

    在移动端 触屏click事件虽然也会响应,但是总感觉是有延迟,一直听说click事件在手机上有200~300毫秒的延迟问题,亲自测了一下,在pc端模拟手机的话是测不出来的,但是用手机测试时发现延迟非常 ...

  7. [题解] CF932E Team Work

    CF932E Team Work 你现在手里有\(n\)个人,你要选出若干个人来搞事情(不能不选),其中选择\(x\)个人出来的代价是\(x^k\),问所有方案的代价总和. 数据范围:\(1\le n ...

  8. 实验吧-隐写术-男神一般都很低调很低调的!!(stegsolve->Image Combiner + DES加密)

    先介绍一下DES加密:(也可参考https://blog.csdn.net/zz_Caleb/article/details/87016017,第14个) 1)对称加密,参考:对称加密和非对称加密 2 ...

  9. 怎么在一个servlet中实现多个功能 ?如何使一个Servlet处理多个请求?

    自学javaweb一直不知道一个servelt可以有多个功能!看了别人代码才知道这个可以有! 平时你建立servelt时候你会吧doget和dopost这两个勾上,要想实现多个功能,你不必要勾选dog ...

  10. 十三、react-router 4.x的基本配置

    路由的定义及作用 根组件根据客户端不同的请求网址显示时,要卸载上一个组件,再挂载下一个组件,如果手动操作话将是一个巨大麻烦.具体过程如下图: [根组件] ↑ [首页组件] [新闻组件] [商品组件] ...