web项目启动流程探索
在web项目的启动过程中,我们希望知道它的一般流程是什么,这样我们就可以在各个流程中加入相应的功能,或者对于我们排错也有帮助。
我们知道,当我们启动tomcat容器以后,容器首先初始化一些必要的组件,加载项目所引用到的jar包(分别从jdk,tomcat,还有web-inf中的lib目录下),然后接下来的一步就是去读取web项目的web.xml配置文件。所以web项目里面必须要有web.xml配置文件。
我们来看一份标准的web.xml配置文件,这是我从我的项目中抽取出来的。
<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_1.xsd"
version="3.1">
<!-- spring上下文 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:ApplicationContext.xml,
</param-value>
</context-param>
<!-- 加载log4j配置文件 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>www.warrior.com</param-value>
</context-param>
<!-- 监听器 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 字符编码过滤器 -->
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 初始化filter -->
<filter>
<filter-name>startFilter</filter-name>
<filter-class>com.xdx.filter.StartFilter</filter-class>
</filter>
<!-- session过滤器 -->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 以下配置是spring mvc -->
<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:ApplicationContext-mvc.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>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<session-config>
<session-timeout>600</session-timeout>
</session-config>
</web-app>
可以看出web.xml的主要配置项有如下几种。
a.context-param:上下文参数,通过键值对的方式配置一些上下文信息,如contextConfigLocation,我们给他配置为classpath:ApplicationContext.xml,说明去classpath:ApplicationContext.xml这个地方去寻找spring的主配置文件。
b.listener:listener就是监听器,他会监听一些变化(比如servlet的初始化),然后就可以触发监听器的代码了。
c.filter:过滤器,顾名思义,就是对请求进行过滤,filter也会在项目启动的时候被实例化。一般一个filter要对应filter-mapping,用于筛选所要执行过滤器中代码的url路径。如果一个filter没有filter-mapping,那它存在的意义就不大,它在web.xml存在的目的纯粹就是为了在项目启动的时候被实例化,从而执行其内部的代码。上述配置文件中的startFilter就是这个作用。
d.servlet,servlet的配置与filter类似,就是对请求进行拦截,不同的请求分配到不同的servlet类进行处理。
为了观察项目中各组件的启动顺序,我在相关的dao,entity类,service类,controllers类均加上了static代码块和无参的构造函数。static代码块是在类加载的时候运行,构造函数在类实例化时候运行,如下所示。

运行项目。看看控制台打印出来的日志。

我们可以看到,项目的启动顺序首先是context-param,接着是listener,在接下来是filter,最后才是servlet。
问题1:改换context-param,listener,filter,servlet配置语句在web.xml中的顺序,其启动顺序是否会变呢?
答案是否定的,即便是吧关于servlet的配置放在最前面,其加载顺序还是会在最后。但是需要注意的是,在同一类型的配置项中,其在web.xml的顺序会影响其启动的顺序,比如有两个filter,filter1在配置文件中先于filter2,则filter1先于filter2被加载实例化。
问题2:org.springframework.web.context.ContextLoaderListener的作用。
ContextLoaderListener这个监听器继承自ContextLoader并且实现了ServletContextListener,他的主要作用是去寻找并读取spring主配置文件ApplicationContext.xml(也就是context-param中所定义的contextConfigLocation),然后启动WebApplicationContext,也可叫做web应用上下文,并且最重要的是,它将WebApplicationContext注入到servletContext容器中(作为servletContext的一个attribute,属性),并且在WebApplicationContext中保留了一个servletContext的引用。所以我们可以通过
WebApplicationContext得到servletContext,也可以通过servletContext获取到WebApplicationContext。
通过WebApplicationContext得到servletContext:
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext servletContext = webApplicationContext.getServletContext();
通过servletContext获取WebApplicationContext:
ServletContext servletContext = event.getServletContext();
ApplicationContext application = WebApplicationContextUtils .getWebApplicationContext(servletContext);
问题3:webApplicationContext和servletContext是谁先存在呢?
当然是servletcontext,ServletContext是web容器(tomcat等)为web项目提供的一个全局上下文,一个web项目中只有一个。它其实是后面生成的WebApplicationContext容器的一个宿主。
所以:简单来说:web项目启动经过如下步骤。
1.项目启动,加载依赖的jar包。
2.web容器(tomcat)先提供一个全局上下文ServletContext.
3.web容器去读取web.xml文件,并且运行ContextLoaderListener监听器,该监听器因为实现了ServletContextListener接口,所以当发现容器生成了一个ServletContext实例的时候,便会执行ServletContextListener接口的初始化方法,在该初始化方法中根据contextConfigLocation指定的位置去读取spring的主要配置文件,然后生成web应用上下文WebApplicationContext,并且将其作为一个属性注入到ServletContext中。
4.初始化WebApplicationContext以后,启动了“业务层”的spring容器,并开始加载病初始化applicationContext配置文件中所扫描的类。
5.然后就是初始化filter,最后初始化servlet。
所以说作为web项目,WebApplicationContext的生成必须要在web容器存在的情况下才能实现,因为他需要ServletContext,而ServletContext是web容器生成的。
问题4:DispatcherServlet是什么?有什么用。
简单来说,它就是一个servlet,但是它是一个特殊的servlet,是整个spring mvc框架的核心,他是一个前端servlet,spring mvc经过前端servlet来接受所有的请求,然后再讲具体工作派发给其他的的servlet来具体实现。
同时,再servlet的配置文件中,我们看到名为SpringMvc的读取了contextConfigLocation所定义的配置文件(classpath:ApplicationContext-mvc.xml),启动了web层的spring容器,在这个容器里,我们初始化了所有的controller类。如控制台打印的日志所示。
问题5:由于初始化DispatcherServlet伴随着启动spring mvc容器(即上面所说的web层容器),所以需要较长的时间,所以我们希望在项目启动的时候就进行初始化的操作。这也是我们将load-on-startup项设为1的原因。因为这个属性设为正数的表示在项目启动的时候就初始化,数字越小表明越早初始化。如果我们将其设为负数的话。那么在项目启动的时候,将不会启动spring mvc的容器,而是当我们第一次访问某个controller所对应的action的时候才来加载启动容器,这将会造成较长时间的等待,所以我们一般将load-on-startup设为1.
web项目启动流程探索的更多相关文章
- 05、NetCore2.0依赖注入(DI)之Web应用启动流程管理
05.NetCore2.0依赖注入(DI)之Web应用启动流程管理 在一个Asp.net core 2.0 Web应用程序中,启动过程都做了些什么?NetCore2.0的依赖注入(DI)框架是如何管理 ...
- web理论知识--网页访问过程(附有Django的web项目访问流程)
当我们闲暇之余想上网看看新闻,或者看个电影,通常的操作是:打开电脑.打开浏览器.输入网址.浏览页面信息.点击自己感兴趣的连接......那么有没有想过,这些网页从哪里来的?过程中计算机又做了什么事情了 ...
- 一个简单的Java Web项目搭建流程
今天试图在服务器上搭建一个web服务器,顺便回顾了java web项目的入门,使用Servlet处理HTTP请求,并记录日志等操作.当很久没有做过web项目时,有些东西还是很容易忘记的. Maven配 ...
- 关于idea中,web项目启动tomcat,访问资源报错404
背景: web项目启动tomcat,访问相应的资源,报错404,前提资源路径是没错的. 原因: 1.确定是不是web项目 不是的话: 配置web-inf的路径和webroot(web根目录)的路径 2 ...
- web项目开发流程
对于一个web项目,在实际编码之前,有一些通用的步骤来planning a website: 0.Defining the project (predr0->dr0) 对于外部项目,客户一般会发 ...
- PC端Web项目开发流程
从前一直再做前端,突然想到如果有一天领导让自己独立承担一个web 项目的话是否有足够的能力去接这个任务,要学会自己去搭建一些基础的工具信息.所有的这一切在心里都要有个大致的流程,不然真正做的时候难免会 ...
- 在web项目启动时,使用监听器来执行某个方法
在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 这里写了个简 ...
- maven的java web项目启动找不到Spring ContextLoaderListener的解决办法
用maven搭建的java web项目,上传到git仓库后,当同事clone下来项目,部署到tomcat运行时,就报了如下错误,即启动web项目时,加载web.xml文件,找不到spring的监听器, ...
- 在web项目启动时,执行某个方法
在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 在工作中遇到 ...
随机推荐
- Linux常用配置讲解
本文主要讲解Linux的用户设置.主机名设置.网络配置.防火墙配置 用户传输包的命令lrzsz的安装以及SSH服务配置等基本操作. 1. 用户名设置 服务肯定是为了用户,而用户可能对于Linux并不了 ...
- let 和const与var的不同
1. let的作用域在代码块中仅限在当前的作用于中 { var str1 = 12; console.log(str1); let str2 = 20; console.log(str2); //20 ...
- android wear开发之:建立可穿戴设备的应用 - Building Apps for Wearables
注:本文内容来自:https://developer.android.com/training/building-wearables.html 翻译水平有限,如有疏漏,欢迎批评指教. 译:山人 建立可 ...
- C# 中英文符号互转
/// 转全角的函数(SBC case) /// ///任意字符串 /// 全角字符串 /// ///全角空格为12288,半角空格为32 ///其他字符半角(33 ...
- 很考验人的java内存加载面试题
源代码如下,求结果 public class MemoryAnalyse { public static int k = 0; public static MemoryAnalyse t1 = new ...
- shell全自动登录远程终端
先看效果 你需要做的事情,在配置文件中配置服务器信息,选择对应的服务器,进行连接. 传统手工连接 #密码方式 ssh user@ip # 然后输入服务器密码 #密钥登录 ssh -i identity ...
- linux 安装nginx 详解
1 nginx安装环境 nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境. n gcc 安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没 ...
- 基于docker+reveal.js搭建一个属于自己的在线ppt网站
前言 最近热衷于Docker,由于这段时间使用Docker来折腾自己的服务器,越来越感觉这是一种及其被应该推广的技术,因此想在公司内部也做一次技术分享.当然,如果只是做的PPT,我就不写这文章了.既然 ...
- android 开源收藏
第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...
- 十五、Hadoop学习笔记————Zookeeper的环境搭建
linux中/opt一般用来存放应用/var目录一般用来存放日志 sample为样例文件,复制一份zoo.cfg文件 配置zoo文件,id为服务器id(整数),host为服务器的ip地址,第一个por ...