精华内容
下载资源
问答
  • web项目执行顺序
    万次阅读
    2017-09-05 15:24:00

    一、web.xml配置节点简介

    (1) context-param

    • 格式定义
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-mybatis.xml</param-value>
    </context-param>
    • 作用:该元素用来声明应用范围(整个WEB项目)内的上下文初始化参数。
      param-name 设定上下文的参数名称。必须是唯一名称
      param-value 设定的参数名称的值,这里的例子是指定spring配置文件的位置

    (2) listener

    • 格式定义
    //listen-class 指定监听类,该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event)
    <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    • 作用:该元素用来注册一个监听器类。可以收到事件什么时候发生以及用什么作为响应的通知。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。

    (3) filter

    • 格式定义
    <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>
    • 作用:用于指定WEB容器的过滤器, filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应;在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;根据程序需要修改请求和响应;在servlet被调用之后截获servlet的执行。

    (4)servlet
    - 格式定义

    //配置Spring MVC,指定处理请求的Servlet,有两种方式:
    //1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml
    //2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。
    //这里使用的是第二种方式
    
    <!-- Springmvc的核心控制器 -->
        <servlet>
            <servlet-name>dispatchServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatchServlet</servlet-name>
            <url-pattern>*.shtml</url-pattern>
        </servlet-mapping>
    • 作用: 创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
      创建可嵌入到现有的html页面中的一部分html页面(html片段);
      读取客户端发来的隐藏数据;
      读取客户端发来的显示数据;
      与其他服务器资源(包括数据库和java的应用程序)进行通信;

    二、 web.xml加载过程(步骤):

    1. 启动web项目,容器(如Tomcat、Apache)会去读取它的配置文件web.xml 中的两个节点,context-param和listener。
    2. 紧接着,容器将创建一个ServletContext(又称为:Servlet上下文),应用范围内即整个WEB项目都能使用这个Servlet上下文。
    3. 容器将< context-param >转化为键值对,并交给ServletContext。
    4. 容器创建< listener >中的类实例,即创建监听。(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)。
    5. 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter(“context-param的键”); 在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法。用于关闭应用前释放资源,比如说数据库连接的关闭。
    6. 得到这个context-param的值之后,你就可以做一些操作了。注意,这个时候你的WEB项目还没有完全启动完成。这个动作会比所有的Servlet都要早。
      换句话说,这个时候,你对 < context-param > 中的键值做的操作,将在你的WEB项目完全启动之前被执行。
    7. 举例.你可能想在项目启动之前就打开数据库。那么这里就可以在< context-param >中设置数据库的连接方式,在监听类中初始化数据库的连接。

      补充知识:ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。例如,一个购物网站,用户要访问商品的详细信息,如果放在session域,每个用户都要访问一遍数据库,这样效率太低;而放在ServletContext中,服务器一启动,就访问数据库将商品信息放入数据库,这样所有用户只需要通过上下文就能访问到商品的信息。

    三、web.xml节点加载顺序:

    • web.xml节点的加载顺序与它们在web.xml中位置的先后无关,即不会因为< filter >写在< context-param >前面就先加载< filter >。
    • 上文也提到到了,< context-param >用于对ServletContext提供键值对,即应用程序的上下文信息。而listener、servlet等节点在初始化的过程中会使用到这些上下文信息,所以最后我们得出web.xml节点的加载顺序应该为:context-param->listener->filter->servlet。
    • 对于某类配置节点而言,位置的先后是有要求的。以servlet举例,与servlet相关的配置节点是servlet-mapping,对于拥有相同配置节servlet-name的servlet和servlet-mapping来说,servlet-mapping必须在servlet后定义,否则当解析到servlet-mapping时,它的servlet-name还没有定义。web 容器启动时初始化每个 servlet时,是按照 servlet配置节出现的顺序来初始化的。
    • 最终结论: web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
    更多相关内容
  • 主要介绍了详解Java Web项目启动执行顺序,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • web项目加载顺序

    千次阅读 2018-11-19 00:01:31
    web项目执行顺序 现在主流的web开发框架一般都是基于Spring开发的,Spring生态圈量级非常之大,功能非常强大。今天讲述一下普通的web项目加载顺序。 虽然项目大部分都在使用SpringBoot、SpringCloud等微服务的架构来...

    @WEB

    web项目执行顺序

    现在主流的web开发框架一般都是基于Spring开发的,Spring生态圈量级非常之大,功能非常强大。今天讲述一下普通的web项目加载顺序。 虽然项目大部分都在使用SpringBoot、SpringCloud等微服务的架构来搭建项目,基本不会在进行这些配置了,但是如果项目追究Spring源码,这些基础知识还是需要了解的。

    1. web.xml
      web项目运行时首先会加载web.xml配置文件,一般该配置文件在 /WebRoot(web)/WEB-INF/web.xml ,web.xml中的内容加载不依赖于内容书写顺序,而是以 context-param 、 listener、 filter、servlet的顺序进行加载。web.xml中有以下几项内容:
      (1)context-param
      以下为配置spring配置文件目录的配置。该配置是针对整个web项目上下文的。

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

      (2)listener
      该配置用于向web容器中注册一个事件监听器,监听事件发生事件,如何响应等信息。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。

      <listener>
         // 该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event)
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      

      (3)filter
      filter 在web项目中起到过滤请求的作用,可配置在web.xml中,也可在项目中使用代码 继承Filter类来进行处理一些逻辑。Filter类中有 init(), doFilter(),destory() 方法。可获取到请求ServletRequest 和ServletResponse,然后决定继续处理哪些请求,阻挡哪些请求等。一般用作 防CRSF攻击、防SQL注入、权限过滤等
      web.xml中filter 需要和 filter-mapping 一起使用,如下为字符过滤器。

      <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>
      
      public interface Filter {
        default void init(FilterConfig filterConfig) throws ServletException {}
        void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
        default void destroy() {}
      }
      

      (4)servlet
      SpringMVC 中围绕 DispatcherServlet 来设计请求映射、视图处理、视图解析。DispatcherServlet 用于处理请求分发。具体内容见后续SpringMVC执行顺序。

      <servlet>
          <servlet-name>dispatcherServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:SpringMVC.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
        </servlet>
        
        <servlet-mapping>
          <servlet-name>dispatcherServlet</servlet-name>
          <url-pattern>*.do</url-pattern>
        </servlet-mapping>
      

      (5)欢迎页
      web项目默认启动加载的页面。

      <welcome-file-list>
          <welcome-file>.html</welcome-file>
          <welcome-file>index.htm</welcome-file>
          <welcome-file>index.jsp</welcome-file>
          <welcome-file>default.html</welcome-file>
          <welcome-file>default.htm</welcome-file>
          <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
      

    SpringMVC执行顺序

    1. 时序图

    在这里插入图片描述

    2.组件

    DispatcherServlet

    前端控制器DispatcherServlet是SpringMVC整个流程控制中心,由它来调度其它组件相互配合,完成匹配请求URL,解析数据,响应数据,视图解析以及视图渲染等任务。

    HandlerMapping

    处理器映射器HandlerMapping负责根据用户请求URL找到匹配的Handler处理器。

    HandlerAdapter

    处理器适配器HandlerAdapter对处理器进行执行

    ModelAndView

    ModelAndView是Spring封装的model和view组合对象。可用于处理数据和视图。

    ViewResolver

    视图解析器ViewResolver负责处理结果生成视图,先根据逻辑视图名称找到物理视图地址,再生成视图对象,最后对视图进行渲染,将处理结果通过页面展现给用户。

    Controller

    业务逻辑处理器,接受请求参数,进行业务处理,返回响应的数据和视图。
    3.applicationContext.xml和dispatcher-servlet.xml
    applicationContext.xml 是Spring的全局配置文件,用来控制Spring特性,管理Bean的容器。
    dispatcher-servlet.xml是SpringMVC中用作控制器,拦截器、转发view等作用。

    注意

    在两个配置文件中最好不要声明相同的bean。 applicationContext.xml是随ContextLoaderListener而加载的,ContextLoaderListener 配置于 中的。dispatcher-servlet.xml是随DispatcherServlet而加载的,而DispatcherServlet配置于 中,在web.xml中加载顺序为 context-param 、listener 、 filter 、servlet 。所以先加载applicationContext.xml 再加载dispatcher-servlet.xml

    展开全文
  • Java Web项目启动时。web.xml执行顺序

    千次阅读 2018-05-07 10:47:03
    转载出处:https://blog.csdn.net/qq_20805103/article/details/77851996 一、web.xml配置节点简介 (1) context-param 格式定义 &lt;context-param&gt; &lt;param-name&gt;context...

    转载出处:https://blog.csdn.net/qq_20805103/article/details/77851996



    一、web.xml配置节点简介

    (1) context-param

    • 格式定义
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-mybatis.xml</param-value>
    </context-param>
     
    • 1
    • 2
    • 3
    • 4
    • 作用:该元素用来声明应用范围(整个WEB项目)内的上下文初始化参数。
      param-name 设定上下文的参数名称。必须是唯一名称
      param-value 设定的参数名称的值,这里的例子是指定spring配置文件的位置

    (2) listener

    • 格式定义
    //listen-class 指定监听类,该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event)
    <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     
    • 1
    • 2
    • 3
    • 4
    • 作用:该元素用来注册一个监听器类。可以收到事件什么时候发生以及用什么作为响应的通知。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。

    (3) filter

    • 格式定义
    <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>
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 作用:用于指定WEB容器的过滤器, filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应;在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;根据程序需要修改请求和响应;在servlet被调用之后截获servlet的执行。

    (4)servlet
    - 格式定义

    //配置Spring MVC,指定处理请求的Servlet,有两种方式:
    //1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml
    //2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。
    //这里使用的是第二种方式
    
    <!-- Springmvc的核心控制器 -->
        <servlet>
            <servlet-name>dispatchServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatchServlet</servlet-name>
            <url-pattern>*.shtml</url-pattern>
        </servlet-mapping>
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 作用: 创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
      创建可嵌入到现有的html页面中的一部分html页面(html片段);
      读取客户端发来的隐藏数据;
      读取客户端发来的显示数据;
      与其他服务器资源(包括数据库和java的应用程序)进行通信;

    二、 web.xml加载过程(步骤):

    1. 启动web项目,容器(如Tomcat、Apache)会去读取它的配置文件web.xml 中的两个节点,context-param和listener。
    2. 紧接着,容器将创建一个ServletContext(又称为:Servlet上下文),应用范围内即整个WEB项目都能使用这个Servlet上下文。
    3. 容器将< context-param >转化为键值对,并交给ServletContext。
    4. 容器创建< listener >中的类实例,即创建监听。(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)。
    5. 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter(“context-param的键”); 在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法。用于关闭应用前释放资源,比如说数据库连接的关闭。
    6. 得到这个context-param的值之后,你就可以做一些操作了。注意,这个时候你的WEB项目还没有完全启动完成。这个动作会比所有的Servlet都要早。
      换句话说,这个时候,你对 < context-param > 中的键值做的操作,将在你的WEB项目完全启动之前被执行。
    7. 举例.你可能想在项目启动之前就打开数据库。那么这里就可以在< context-param >中设置数据库的连接方式,在监听类中初始化数据库的连接。

      补充知识:ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。例如,一个购物网站,用户要访问商品的详细信息,如果放在session域,每个用户都要访问一遍数据库,这样效率太低;而放在ServletContext中,服务器一启动,就访问数据库将商品信息放入数据库,这样所有用户只需要通过上下文就能访问到商品的信息。

    三、web.xml节点加载顺序:

    • web.xml节点的加载顺序与它们在web.xml中位置的先后无关,即不会因为< filter >写在< context-param >前面就先加载< filter >。
    • 上文也提到到了,< context-param >用于对ServletContext提供键值对,即应用程序的上下文信息。而listener、servlet等节点在初始化的过程中会使用到这些上下文信息,所以最后我们得出web.xml节点的加载顺序应该为:context-param->listener->filter->servlet。
    • 对于某类配置节点而言,位置的先后是有要求的。以servlet举例,与servlet相关的配置节点是servlet-mapping,对于拥有相同配置节servlet-name的servlet和servlet-mapping来说,servlet-mapping必须在servlet后定义,否则当解析到servlet-mapping时,它的servlet-name还没有定义。web 容器启动时初始化每个 servlet时,是按照 servlet配置节出现的顺序来初始化的。
    • 最终结论: web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
    展开全文
  • 1. 为什么项目Controller的接口方法没有进入拦截器的preHandle? 2. 拦截器定义 3.如果preHandle返回为false,接下来会执行什么? 4. 多拦截器处理顺序? 5. 理论知识 5.1 prehandle 5.2 拦截器的基本概念? ...

    目录

    前言:

    1. 为什么项目Controller的接口方法没有进入拦截器的preHandle?

    2. 拦截器定义

    3.如果preHandle返回为false,接下来会执行什么?

    4. 多拦截器处理顺序?

    5. 理论知识

    5.1 prehandle

    5.2 拦截器的基本概念?

    5.3 什么是servlet容器?

    5.4 什么是过滤器?

    5.4 拦截器与过滤器的区别

    5.5 监听器

    5.6 拦截器与过滤器的使用场景


    前言:

    最近总是整合和联系搭建项目,所以根据不同的需求有着不同的拦截器的写法,以及有的需求会有多个拦截器。

    而拦截器用于 日志记录、用户登录状态拦截、安全拦截等等。

    我的感情 我的人性 穿越世纪

    你的记忆 你的秘密 依然清晰

    我的回忆 我的思绪 不停累积

    有你在一起 你是专属唯一

                                                                                                                                                               ——《Wonderland》JJ 

    1. 为什么项目Controller的接口方法没有进入拦截器的preHandle?

    原因是因为拦截器的配置还要进行注入。

    拦截器也是需要代码中加入进去的。类似于这样。

    @Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
    
        @Autowired
        private RequestInterceptor requestInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //本项目把所有的路径都加入到拦截的请求中,根据需求可以具体来添加内容
            registry.addInterceptor(requestInterceptor).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
    
        /**
         * 继承前端代码
         * @param registry
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
            super.addResourceHandlers(registry);
        }
    }

    2. 拦截器定义

    package com.switcher.common.intercepter;
    
    import com.switcher.common.constant.ErrorConstants;
    import com.switcher.common.constant.SystemConstants;
    import com.switcher.data.Result;
    import com.switcher.utils.FastJsonUtils;
    import com.switcher.utils.ThreadLocalUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.lang.Nullable;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @Description : RequestInterceptor
     * 拦截处理类
     * <p>
     *  preHandle按拦截器定义顺序调用
     *  postHandler按拦截器定义逆序调用
     *  afterCompletion按拦截器定义逆序调用
     *  postHandler在拦截器链内所有拦截器返成功调用
     *  afterCompletion只有preHandle返回true才调用
     * </p>
     * <p>
     *     支持异步线程方法中可能取不到值
     * @Date : 2019/10/12
     * @Author : pmdream
     */
    @Component
    @Slf4j
    public class RequestInterceptor implements HandlerInterceptor {
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            // 将请求初始参数存入threadLocal
            ThreadLocalUtil.setIsCacheFlag(false);
            //是否需要cache
            ThreadLocalUtil.setNeedCacheFlag(false);
            ThreadLocalUtil.setResponse(response);
            ThreadLocalUtil.setStartTime(System.currentTimeMillis());
            //把请求中的globalRequestId 存入
            String globalRequestId = request.getHeader(SystemConstants.REQUEST_ID);
            ThreadLocalUtil.setRequestId(globalRequestId);
            String userId = request.getHeader(SystemConstants.USER_ID);
            ThreadLocalUtil.setUserId(userId);
            String token = request.getHeader(SystemConstants.REQUEST_TOKEN_KEY);
            if (!SystemConstants.REQUEST_TOKEN_VALUE.equals(token)) {
                log.info("token验证异常! GlobalRequestId = {}", globalRequestId);
                PrintWriter writer = null;
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json; charset=utf-8");
                try {
                    writer = response.getWriter();
                    Result result = new Result(ErrorConstants.TOKEN_ERROR_MSG, ErrorConstants.TOKEN_ERROR_CODE, null, null);
                    writer.print(FastJsonUtils.toJsonString(result));
                    return false;
                } catch (IOException e) {
                    log.error("response返回响应信息异常!", e);
                } finally {
                    if (writer != null) {
                        writer.close();
                    }
                }
            }
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
            long totalTime = ThreadLocalUtil.getTotalTime();
            log.info("===time===请求处理结束,总耗费时间:{}ms, 请求GlobalRequestId = {}", totalTime, ThreadLocalUtil.getRequestId());
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
            ThreadLocalUtil.remove();
        }
    
    }
    

    3.如果preHandle返回为false,接下来会执行什么?

    通过代码调试,发现如果返回false的话,是不会在进入postHandle 和afterCompletion

    相当于预处理就已经出错了。

    正常流程,pre - post -after

    但是如果返回false 的话,那么就会直接在pre里面处理掉了。

    当它返回为false 时,表示请求结束,后续的Interceptor 和Controller都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    那么如果是fasle,进入底层断点一下,再看一下底层的执行逻辑。

    4. 多拦截器处理顺序?

    一般来说,可以写两个拦截器或者更多拦截器,对于请求的URI不同,

    然后进行不同的拦截器。

    当然,如果有多个拦截器对一个请求路径呢?执行的顺序会是怎么样?

    https://blog.csdn.net/syslbjjly/article/details/90675223

    所以,正常放行情况

    那么如果是异常情况呢?

    拦截器都是链式的执行的,如果第一个pre就返回false,是不会进入第二个拦截器的。

    -----如果第一个为true,第二个为false(只要有一个pre为false 也就是拦截器不放行,那么post就不会执行)

    但是正常执行的拦截器,也就是放行的拦截器,是一定要执行afterCompletion()的。

    已经自己校验过,图的话取得是上面链接博主的。

    5. 理论知识

    5.1 prehandle

    SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法

    5.2 拦截器的基本概念?

    拦截器不依赖与Servlet容器,依赖于Spring等web框架。

    拦截器是一种AOP的应用,底层是用的是Java反射机制来实现的。

    于过滤器的很大区别是拦截器可以注入Spring的bean,这个通过上面的代码就可以看出来了。

    拦截器在springboot的配置中就是可以用@Bean 注解 或者@Autowired 来进入。

    拦截器与过滤器最大的区别可能是拦截器注入到Spring的 bean,能够获取到各种需要的Service来处理业务逻辑,

    而过滤器不行。

    拦截器可以继承HandlerInterceptorAdapter 或者HandlerInterceptor来实现。

    另外,MVC的项目中的配置:

    在spring-mvc的xml文件中,大体是这样的:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <import resource="classpath:view/view.xml"/>
    
        <import resource="classpath:security/security-mvc.xml"/>
    
        <mvc:annotation-driven/>
    
        <mvc:interceptors>
            <bean class="xxx.web.common.ApiLogInterceptor"/>
        </mvc:interceptors>
    
        <mvc:interceptors>
            <bean class="xxx.web.common.CORSInterceptor"/>
        </mvc:interceptors>
    
        <mvc:interceptors>
            <bean class="xxx.web.common.LoginInterceptor"/>
        </mvc:interceptors>
    
        <mvc:interceptors>
            <bean class="xxx.web.common.RequestLimitsInterceptor"/>
        </mvc:interceptors>
    
        <!-- 加载Controller -->
        <context:component-scan base-package="xxx" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    </beans>

    所以,springboot还是简化了不少的东西。

    拦截器的执行顺序:如果MVC的话语web.xml 里面配置的顺序有关,链式执行。

    如果是springboot的话,那么就是在webMvc的配置文件中,注册的先后顺序。

    PS:这里可能会被问到@Autowired到底是什么,相当于什么样的过程。

    也可能面试官会引出AOP的相关概念,之后再补充。

    5.3 什么是servlet容器?

    https://blog.csdn.net/yw_1207/article/details/78706701

    5.4 什么是过滤器?

    Filter,依赖于Servlet容器,配置到web.xml文件中。也可以配置多个,执行的顺序是按照配置顺序的从上到下。

    常用来配置一些请求编码和过滤一些非法参数,垃圾信息,或者是网站登录的验证码。

    (主要总结   : 依赖容器,过滤非法参数和编码。)

    在我们的老的项目中,配置是这样的:

    <filter>
    		<filter-name>springSecurityFilterChain</filter-name>
    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>springSecurityFilterChain</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<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>

    不过只看配置文件,大体能看出,拦截器的配置是需要mapping的,也就是针对什么URI来进行不同的拦截,默认的话可以对全部路径进行拦截。

    然后看拦截器是指定了编码格式,比如UTF-8。

    一种实现:(来自博主:https://blog.csdn.net/javageektech/article/details/94250382

    大体上过滤器还是用来验证登录验证码用的,我们项目都没有配置过滤器,因为登录比较简单。

    public class CaptchaFilter implements Filter {    public void init(FilterConfig config) throws ServletException {    }    public void destroy() {    }    public void doFilter(ServletRequest servletRequest,            ServletResponse servletResponse, FilterChain filterChain)            throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) servletRequest;        HttpServletResponse response = (HttpServletResponse) servletResponse;        String servletPath = request.getServletPath();        //获取验证码        if(servletPath.matches("/captcha.jpg")) {            response.setContentType("image/jpeg");            //禁止图像缓存。            response.setHeader("Pragma", "no-cache");            response.setHeader("Cache-Control", "no-cache");            response.setDateHeader("Expires", 0);            //参数:宽、高、字符数、干扰量            CaptchaProductor vCode = new CaptchaProductor(70,30,4,75);            //根据token保存验证码内容            CaptchaBean bean = new CaptchaBean();            bean.setCaptcha(vCode.getCode());            bean.setCreateTime(new Date());            HttpSessionUtils.setSessionValue(request, "sessionCaptcha", bean);            vCode.write(response.getOutputStream());            return;        }    }}class CaptchaFilter implements Filter {
    
    
        public void init(FilterConfig config) throws ServletException {
        }
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest servletRequest,
                ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String servletPath = request.getServletPath();
            //获取验证码
            if(servletPath.matches("/captcha.jpg")) {
                response.setContentType("image/jpeg");
                //禁止图像缓存。
                response.setHeader("Pragma", "no-cache");
                response.setHeader("Cache-Control", "no-cache");
                response.setDateHeader("Expires", 0);
                //参数:宽、高、字符数、干扰量
                CaptchaProductor vCode = new CaptchaProductor(70,30,4,75);
    
                //根据token保存验证码内容
                CaptchaBean bean = new CaptchaBean();
                bean.setCaptcha(vCode.getCode());
                bean.setCreateTime(new Date());
                HttpSessionUtils.setSessionValue(request, "sessionCaptcha", bean);
                vCode.write(response.getOutputStream());
                return;
            }
        }
    }
    

    过滤器的实现可以通过实现 Filter 接口或者继承 Spring 的org.springframework.web.filter.OncePerRequestFilter 来实现。

    5.4 拦截器与过滤器的区别

    过滤器就是筛选出你要的东西,比如requeset中你要的那部分(筛选)
    拦截器在做安全方面用的比较多,比如终止一些流程(请求进入的再次拦截)

    过滤器:

    在实现上基于函数回调,可以对几乎所有请求进行过滤;
    缺点是一个过滤器实例只能在容器初始化时调用一次;
    使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。
     

    拦截器:

    依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架;
    在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用;
    缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理;
    由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

    总结:

    拦截器是基于java的反射机制的,而过滤器是基于函数回调。

    拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

    拦截器只能对action请求起作用(进入controller的),而过滤器则可以对几乎所有的请求起作用(包括静态页面)。

    拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

    在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

    拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

    5.5 监听器

    监听器的作用是监听一些事件的发生从而进行一些操作,比如监听ServletContext,HttpSession的创建,销毁,从而执行一些初始化加载配置文件的操作,

    当Web容器启动后,Spring的监听器会启动监听,监听是否创建ServletContext的对象,如果发生了创建ServletContext对象这个事件(当web容器启动后一定会生成一个ServletContext对象,所以监听事件一定会发生),ContextLoaderListener类会实例化并且执行初始化方法,将spring的配置文件中配置的bean注册到Spring容器中,

    监听的操作是读取WEB-INF/applicationContext.xml,但是我们可以在web.xml中配置多个需要读取的配置文件,如下方所示,读取完成后所有的配置文件中的bean都会注册到spring容器中。

    比如监听 ServletContext对象:

    public void contextInitialized(ServletContextEvent event);  
    public void contextDestoryed(ServletContextEvent event);  

    监听HttpSessionListener 对象:

    publicvoid sessionCreated(HttpSessionEvent event);   
    publicvoid sessionDestoryed(HttpSessionEvent event);  

    监听HttpRequestListener 对象:

    public void requestinitialized(ServletRequestEvent event);  
    public void requestDestoryed(ServletRequestEvent event);  

    web.xml的文件配置:

    <listener>
    		<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
    	</listener>
    	<!--<listener>-->
    		<!--<listener-class>-->
    			<!--org.springframework.web.util.IntrospectorCleanupListener</listener-class>-->
    	<!--</listener>-->
    
    	<!-- 加载通用的bean -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:xxx-servlet.xml</param-value>
    	</context-param>
    	<listener>
    		<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    	</listener>
    	<listener>
    		<listener-class>
    			org.springframework.web.context.request.RequestContextListener
    		</listener-class>
    	</listener>

    上述配置提到的:HttpSessionEventPublisher 和ContextLoaderListener 就是监听器的一部分功能。

    比如mvc项目自己定义监听器:

    <listener>  
            <listener-class>listener.MyListener</listener-class>  
        </listener>  

    5.6 拦截器与过滤器的使用场景

    SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

    1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。

    2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;

    3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);(项目中拦截器记录了时间)

    4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。

    5、OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。
    (这个暂时没用到)

    拦截器是AOP的一种实现,底层通过动态代理模式完成。(动态代理面试必问)

    转自:https://www.cnblogs.com/lwh0206/p/7170029.html

    展开全文
  • 通过web.xml中控制filter-mapping的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行 <!-- 用户登录检测过滤器 --> <filter> <filter-...
  • jenkins构建多个项目执行顺序设置

    千次阅读 2018-07-06 15:37:00
    ,有两个构建项目,posWeb是个web项目,welife是接口项目。 由于接口项目数据会影响posWeb执行。那么,就要设置,先执行welife项目。 配置如下: 由于posWeb是ui项目, 在执行过程中需要前台执行: 1.不使用...
  • 当启动一个WEB项目的时候,容器(比如Tomcat等),首先会读取项目web.xml配置文件里的配置,如果这一步骤不出错且完成之后,项目才能正常启动起来 1、在启动Web项目时,容器(如Tomcat)会首先读web.xml配置文件中的...
  • filter的执行顺序是怎样的?

    千次阅读 2020-12-21 16:25:54
    1.引言我们在编写javaweb程序的时候,时常会用filter这个组件...servlet3.0以前我们只能通过web.xml的方式配置filter,并且多个filter的执行顺序是根据你web.xml中书写顺序来决定的.servlet3.0以后,提供了注解的方式注...
  • SSM框架运行原理web.xml执行顺序

    千次阅读 2018-06-29 13:54:56
    ssm框架 中web.xml执行顺序 1. <!–spring 的监听器–> <listener-class>org.springframework.web.context.ContextLoaderListener 2 <!– spring 主配置文件的 路径 和名字 –> <param-name>...
  • 多个过滤器的执行顺序

    千次阅读 2019-12-10 20:23:39
    一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的部署顺序。 我们演示一下: 我们建立两个filter: AFilter: public void doFilter(ServletRequest request, ServletResponse response, ...
  • 转载自这篇文章可以看到web容器一启动就会实例化监听器的contextInitialized(ServletContextEvent event)方法,然后是过滤器的init()方法,最后在用户访问web应用的 时候会先执行过滤器的doFilter()方法,以及过滤...
  • springboot项目启动后,执行代码顺序

    千次阅读 2020-04-21 14:38:40
    springboot项目启动后,执行代码 SpringApplication的run方法下的 this.refreshContext(context); 执行后,执行继承ApplicationListener接口的类下的contextRefreshedEvent ```java @Component public class ...
  • web项目启动时执行方法的实现方式

    千次阅读 2018-11-24 11:40:09
    web项目启动的时执行方法,实现有好多种,可以分为2大类: 1.使用web自带的: (1)使用servlet,但是他不能使用spring 的bean 还需要手动获取,比较麻烦. (2)创建一个类实现ServletContextListener 接口,实现...
  • 项目从jpa过渡到mybatis,代码整合之后,使用新的数据库连接,项目启动报错,未看到flyway等打印的日志信息,且数据库未生成数据。 报错大概为找不到对应表 org.springframework.context....
  • 一、准备环境: 1.开发工具:Microsoft Visual ...二、创建项目,选择WebAPI: 项目结构如下: 然后对里面每个对象方法添加对应名称的控制台输出语句,改造如下: Program.cs文件内容分别如下: using Sys...
  • web-fragment 中的执行顺序

    千次阅读 2018-03-29 23:28:13
    最近在一个decouple的项目中引入了web-fragment.xml, 遇到了一些问题,比较好玩,记录下。web-fragment.xml 是servlet 3.0 以后引入的,它也是用来提供web部署描述的,功能上跟web.xml是一模一样的。不一样的地方是...
  • 1、方法加@PostConstruct2、实现CommandLineRunner接口,复写run方法 , 如果需要控制多个程序的执行顺序 可以加@order注解3、实现ApplicationRunner接口 这个和 CommandLineRunner 基本一样 , 区别是:...
  • } } 6、控制执行顺序不同 实际开发过程中,会出现多个过滤器或拦截器同时存在的情况,不过,有时我们希望某个过滤器或拦截器能优先执行,就涉及到它们的执行顺序。 过滤器用@Order注解控制执行顺序,通过@Order控制...
  • 一、执行顺序:如果有两个过滤器:过滤器1和过滤器2 1. request请求 1. 过滤器1 2. 过滤器2 2. 访问目标资源 3. 资源执行 3. response响应 4. 过滤器2 5. 过滤器1 二、过滤器先后顺序问题: 1.注解配置:按照...
  • 当过滤器用web.xml配置时,控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如“用户登录检查过滤器”会比“接口日志过滤器”先执行,这种方式一搜一大堆。...
  • Spring 执行顺序:PostProcessor 接口

    千次阅读 2019-08-29 21:12:43
    由于这个配置会影响其他测试的执行顺序(EnvironmentPostProcessor 肯定是第一个),所以本项目中注释了上述配置。 该接口比所有其他 PostProcessor 执行的都早,由于接口特殊,这里不再继续往下进行分析。
  • web项目启动时执行某个方法

    千次阅读 2018-03-31 22:32:38
    web项目启动时执行某个方法的几种方式:指定init-method的Bean执行、实现spring的Bean后置处理器执行、Servlet的监听器执行、Servlet的过滤器执行、Servlet执行。1、实现Servlet监听器接口ServletContextListener...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 168,458
精华内容 67,383
关键字:

web项目执行顺序