• Web项目的启动流程


    在web项目的启动过程中,我们希望知道它的一般流程是什么,这样我们就可以在各个流程中加入相应的功能,或者对于我们排错也有帮助。

    1. 启动tomcat容器以后,容器首先初始化一些必要的组件;
    2. 加载项目所引用到的jar包(分别从jdk,tomcat,还有web-inf中的lib目录下);
    3. 读取web项目的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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/root-context.xml,classpath:spring/bwp-context.xml,classpath:spring/csp-context.xml</param-value>
      </context-param>
      <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
      </listener>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
     <!--  <listener>
        <listener-class>usi.btfb.filter.HttpSessionCollector</listener-class>
      </listener> -->
      
       <!-- session共享过滤器start,此过滤器要放在其他过滤器之前 -->
      <!-- <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> -->
       <!-- session共享过滤器end -->
      
      <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    
     <!--  cxfservlet 
          <servlet>
            <servlet-name>cxf</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>cxf</servlet-name>
            <url-pattern>/service/*</url-pattern>
        </servlet-mapping>-->
    
      <!-- 解决xss & sql漏洞 -->  
      <filter>
        <filter-name>jsFilter</filter-name>
        <filter-class>usi.btfb.filter.SpecialChrEscapeFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>jsFilter</filter-name>
        <url-pattern>*.do</url-pattern>
        <dispatcher>REQUEST</dispatcher>
      </filter-mapping> 
      
      <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>
        <init-param>
          <param-name>forceEncoding</param-name>
          <param-value>true</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    
      <servlet>
        <servlet-name>uiLoaderServlet</servlet-name>
        <servlet-class>usi.sys.servlet.UiLoaderServlet</servlet-class>
        <init-param>
          <param-name>uiConfigLocation</param-name>
          <param-value>classpath:ui/ui.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <filter>
        <filter-name>CheckSessionFilter</filter-name>
        <!-- <filter-class>usi.sys.filter.CheckSessionFilter</filter-class> -->
        <filter-class>usi.btfb.filter.CheckSessionFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>CheckSessionFilter</filter-name>
        <url-pattern>*.do</url-pattern>
      </filter-mapping>
        <filter-mapping>
        <filter-name>CheckSessionFilter</filter-name>
        <url-pattern>*.html</url-pattern>
      </filter-mapping>
      <context-param>
        <param-name>menuFilter</param-name>
        <param-value>true</param-value>
      </context-param>
      <filter>
        <filter-name>MenuAccessFilter</filter-name>
        <filter-class>usi.sys.filter.MenuAccessFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>MenuAccessFilter</filter-name>
        <url-pattern>*.do</url-pattern>
      </filter-mapping>
      <filter>
        <filter-name>lazyLoadingFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>lazyLoadingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter>
        <filter-name>getSessionContentFilter</filter-name>
        <filter-class>usi.sys.filter.GetSessionContentFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>getSessionContentFilter</filter-name>
        <url-pattern>*.do</url-pattern>
      </filter-mapping>
      <session-config>
        <session-timeout>600</session-timeout>
      </session-config>
      <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/views/500.jsp</location>
      </error-page>
      <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/views/404.jsp</location>
      </error-page>
      <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/WEB-INF/views/500.jsp</location>
      </error-page>
      
      <!--druid监控页面 -->
        <servlet>
            <servlet-name>DruidStatView</servlet-name>
            <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
            <init-param>
                <!-- 不允许清空统计数据 -->
                <param-name>resetEnable</param-name>
                <param-value>false</param-value>
            </init-param>
            <!-- <init-param>
              //  用户名
                <param-name>loginUsername</param-name>
                <param-value>admin</param-value>
            </init-param>
            <init-param>
              //  密码
                <param-name>loginPassword</param-name>
                <param-value>GS_zhkf_2019@</param-value>
            </init-param> -->
        </servlet>
        <servlet-mapping>
            <servlet-name>DruidStatView</servlet-name>
            <url-pattern>/druid/*</url-pattern>
        </servlet-mapping>
        <!-- 如果需要监控uri,设置Web关联监控配置 -->
        <filter>
            <filter-name>DruidWebStatFilter</filter-name>
            <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
            <init-param>
                <param-name>exclusions</param-name><!--排除统计干扰 -->
                <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>DruidWebStatFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <!--druid监控页面 -->
    </web-app>

    可以看出web.xml的主要配置项有如下几种。

      a.context-param:上下文参数,通过键值对的方式配置一些上下文信息,如contextConfigLocation,我们给他配置为classpath:ApplicationContext.xml,说明去classpath:ApplicationContext.xml这个地方去寻找spring的主配置文件。

      b.listener:listener就是监听器,他会监听一些变化(比如servlet的初始化),然后就可以触发监听器的代码了。

    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
      </listener>
    <!--
    1、此监听器主要用于解决java.beans.Introspector导致的内存泄漏的问题
    2、此监听器应该配置在web.xml中与Spring相关监听器中的第一个位置(也要在ContextLoaderListener的前面)
    3、JDK中的java.beans.Introspector类的用途是发现Java类是否符合JavaBean规范如果有的框架或程序用到了Introspector类,那么就会启用一个系统级别的缓存,
    此缓存会存放一些曾加载并分析过的JavaBean的引用。当Web服务器关闭时,由于此缓存中存放着这些JavaBean的引用,所以垃圾回收器无法回收Web容器中的JavaBean对象,最后导致
    内存变大。而org.springframework.web.util.IntrospectorCleanupListener就是专门用来处理Introspector内存泄漏问题的辅助类。IntrospectorCleanupListener会在
    Web服务器停止时清理Introspector缓存,使那些Javabean能被垃圾回收器正确回收。Spring自身不会出现这种问题,因为Spring在加载并分析完一个类之后会马上刷新JavaBeans Introspector缓存,
    这就保证Spring中不会出现这种内存泄漏的问题。但有些程序和框架在使用了JavaBeans Introspector之后,没有进行清理工作(如Quartz,Struts),最后导致内存泄漏
    -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    <!--
    作用:启动Web容器时,自动装配ApplicationContext的配置信息
    -->

      c.filter:过滤器,顾名思义,就是对请求进行过滤,filter也会在项目启动的时候被实例化。一般一个filter要对应filter-mapping,用于筛选所要执行过滤器中代码的url路径。如果一个filter没有filter-mapping,那它存在的意义就不大,它在web.xml存在的目的纯粹就是为了在项目启动的时候被实例化,从而执行其内部的代码。上述配置文件中的startFilter就是这个作用。

      d.servlet,servlet的配置与filter类似,就是对请求进行拦截,不同的请求分配到不同的servlet类进行处理。

    启动顺序首先是context-param,接着是listener,在接下来是filter,最后才是servlet。

    所以:简单来说: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容器生成的。

      

      DispatcherServlet是什么?有什么用。

      简单来说,它就是一个servlet,但是它是一个特殊的servlet,是整个spring mvc框架的核心,他是一个前端servlet,spring mvc经过前端servlet来接受所有的请求,然后再讲具体工作派发给其他的的servlet来具体实现。

    同时,再servlet的配置文件中,我们看到名为SpringMvc的读取了contextConfigLocation所定义的配置文件(classpath:ApplicationContext-mvc.xml),启动了web层的spring容器,在这个容器里,我们初始化了所有的controller类。如控制台打印的日志所示。

      

      由于初始化DispatcherServlet伴随着启动spring mvc容器(即上面所说的web层容器),所以需要较长的时间,所以我们希望在项目启动的时候就进行初始化的操作。这也是我们将load-on-startup项设为1的原因。因为这个属性设为正数的表示在项目启动的时候就初始化,数字越小表明越早初始化。如果我们将其设为负数的话。那么在项目启动的时候,将不会启动spring mvc的容器,而是当我们第一次访问某个controller所对应的action的时候才来加载启动容器,这将会造成较长时间的等待,所以我们一般将load-on-startup设为1.

  • 相关阅读:
    guava cache 缓存
    策略模式干掉if-else,switch
    一.投资理论
    死锁问题
    Redis连接数居高不下的问题
    Entity Framework Core To SQL问题
    数据字典
    Core2.0升级2.2
    NetCoreAPI版本控制
    WEBAPI的请求方式与请求类型
  • 原文地址:https://www.cnblogs.com/xiaotang5051729/p/13156741.html
Copyright © 2020-2023  润新知