spring-过滤器,servlet,监听器,拦截器,aop

执行顺序

以前在使用springmvc的时候,也发现没有学的很深。最近得捡起来了
自己写代码试了一下,发现顺序不是严格定义的,因为实现的类,继承的类,不是完全一样的!但是大致的原理却很容易弄懂

2e82ff1d28c5c76e5805c100fdd526ad

565d30037c97b0278af24945fb9e15ea

通过两幅图我们可以理解拦截器和过滤器的特点

过滤器 Filter

  • 过滤器是在请求进入tomcat容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
  • 理解上面这句话我们就可以知道,进入servlet之前,主要是两个参数:ServletRequest,ServletResponse  那我们得到这两个测试可以干哪些事呢?
  • 我们可以通过ServletRequest得到HttpServletRequest,此时你就可以对请求或响应(Request、Response)那就可以对对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息、字符集统一等一些高级功能。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。(每次热部署后,都会销毁)。

拦截器 inteceptor

从上图我们可以看出过滤器只在servlet前后起作用,所以它既不能捕获异常,获得bean对象等,这些是只能是进入servlet里面的拦截器能过做到。拦截器中用于在某个方法或字段被访问之前,进行拦截然后,在之前或之后加入某些操作。比如日志,安全等。一般拦截器方法都是通过动态代理的方式实现。可以通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。

对比一下其实我们可以发现,过滤器能做的事拦截器都能做,而拦截器做的事过滤器不一定做的了。

监听器 listener

listener是servlet规范中定义的一种特殊类。用于监听servletContext、HttpSession和servletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件。用于在事件发生前、发生后做一些必要的处理。其主要可用于以下方面:1、统计在线人数和在线用户2、系统启动时加载初始化信息3、统计网站访问量4、记录用户访问路径。

常用的监听器 servletContextListener、httpSessionListener、servletRequestListener)

如何创建他们

过滤器

自定义Filter 使用Servlet3.0的注解进行配置第三步的@WebFilter就是3.0的注解

  1. 启动类里面增加 @ServletComponentScan,进行扫描

  2. 新建一个Filter类,implements Filter,并实现对应的接口

  3. @WebFilter 标记一个类为filter,被spring进行扫描
    urlPatterns:拦截规则,支持正则

4.控制chain.doFilter的方法的调用,来实现是否通过放行不放行,web应用resp.sendRedirect("/index.html");场景:权限控制、用户登录(非前端后端分离场景)等

@SpringBootApplication
@ServletComponentScan
public class SpringbootstudyApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootstudyApplication.class, args);
    }
}
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

//过滤器拦截路径
@WebFilter(urlPatterns = "/api/*", filterName = "loginFilter")
public class LoginFilter  implements Filter{

     /**
      * 容器加载的时候调用
      */
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
          System.out.println("拦截器进入========拦截器进入========");
      }

      /**
       * 请求被拦截的时候进行调用
       */
      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
          System.out.println("拦截中========拦截中========");

          HttpServletRequest hrequest = (HttpServletRequest)servletRequest;
          HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) servletResponse);
          if(hrequest.getRequestURI().indexOf("/index") != -1 ||
                  hrequest.getRequestURI().indexOf("/asd") != -1 ||
                  hrequest.getRequestURI().indexOf("/online") != -1 ||
                  hrequest.getRequestURI().indexOf("/login") != -1
                  ) {
              filterChain.doFilter(servletRequest, servletResponse);
          }else {
              wrapper.sendRedirect("/login");
          }

      }

      /**
       * 容器被销毁的时候被调用
       */
      @Override
      public void destroy() {
          System.out.println("拦截器销毁========拦截器销毁========");
      }

}

官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners


监听器

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        // TODO Auto-generated method stub
        System.out.println("======销毁监听器========");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("======进入监听器========");

    }

拦截器

CustomWebMvcConfigurer主拦截器需要:
1:添加@Configuration注解
2:实现WebMvcConfigurer接口

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//主拦截器,根据拦截不同路径跳转不同自定义拦截器 (实现WebMvcConfigurer方法)
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer  {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api1/*/**");
        registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api2/*/**");

        //.excludePathPatterns("/api2/xxx/**"); //拦截全部 /*/*/**

        WebMvcConfigurer.super.addInterceptors(registry);
    }

}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoginIntercepter implements HandlerInterceptor{

    /**
     * 进入controller方法之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        System.out.println("LoginIntercepter------->preHandle");

//        String token = request.getParameter("access_token");
//        
//        response.getWriter().print("fail");

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    /**
     * 调用完controller之后,视图渲染之前
     */
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {

        System.out.println("LoginIntercepter------->postHandle");

        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 整个完成之后,通常用于资源清理
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("LoginIntercepter------->afterCompletion");

        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

}

总结

  • 过滤器:用于属性甄别,对象收集(不可改变过滤对象的属性和行为)
  • 监听器:用于对象监听,行为记录(不可改变监听对象的属性和行为)
  • 拦截器:用于对象拦截,行为干预(可以改变拦截对象的属性和行为)

实践

日志:

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Dvisualvm.id=73331820101816 -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=57117:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/tools.jar:/Users/zhaochangqing/Documents/idea/temp/spring-boot/spring-boot-hello2/target/classes:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-starter-web/1.3.3.RELEASE/spring-boot-starter-web-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-starter/1.3.3.RELEASE/spring-boot-starter-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot/1.3.3.RELEASE/spring-boot-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-autoconfigure/1.3.3.RELEASE/spring-boot-autoconfigure-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-starter-logging/1.3.3.RELEASE/spring-boot-starter-logging-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/ch/qos/logback/logback-classic/1.1.5/logback-classic-1.1.5.jar:/Users/zhaochangqing/Documents/idea/repo/ch/qos/logback/logback-core/1.1.5/logback-core-1.1.5.jar:/Users/zhaochangqing/Documents/idea/repo/org/slf4j/slf4j-api/1.7.16/slf4j-api-1.7.16.jar:/Users/zhaochangqing/Documents/idea/repo/org/slf4j/jcl-over-slf4j/1.7.16/jcl-over-slf4j-1.7.16.jar:/Users/zhaochangqing/Documents/idea/repo/org/slf4j/jul-to-slf4j/1.7.16/jul-to-slf4j-1.7.16.jar:/Users/zhaochangqing/Documents/idea/repo/org/slf4j/log4j-over-slf4j/1.7.16/log4j-over-slf4j-1.7.16.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-core/4.2.5.RELEASE/spring-core-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/yaml/snakeyaml/1.16/snakeyaml-1.16.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-starter-tomcat/1.3.3.RELEASE/spring-boot-starter-tomcat-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/apache/tomcat/embed/tomcat-embed-core/8.0.32/tomcat-embed-core-8.0.32.jar:/Users/zhaochangqing/Documents/idea/repo/org/apache/tomcat/embed/tomcat-embed-el/8.0.32/tomcat-embed-el-8.0.32.jar:/Users/zhaochangqing/Documents/idea/repo/org/apache/tomcat/embed/tomcat-embed-logging-juli/8.0.32/tomcat-embed-logging-juli-8.0.32.jar:/Users/zhaochangqing/Documents/idea/repo/org/apache/tomcat/embed/tomcat-embed-websocket/8.0.32/tomcat-embed-websocket-8.0.32.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/boot/spring-boot-starter-validation/1.3.3.RELEASE/spring-boot-starter-validation-1.3.3.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/hibernate/hibernate-validator/5.2.4.Final/hibernate-validator-5.2.4.Final.jar:/Users/zhaochangqing/Documents/idea/repo/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar:/Users/zhaochangqing/Documents/idea/repo/org/jboss/logging/jboss-logging/3.3.0.Final/jboss-logging-3.3.0.Final.jar:/Users/zhaochangqing/Documents/idea/repo/com/fasterxml/classmate/1.1.0/classmate-1.1.0.jar:/Users/zhaochangqing/Documents/idea/repo/com/fasterxml/jackson/core/jackson-databind/2.6.5/jackson-databind-2.6.5.jar:/Users/zhaochangqing/Documents/idea/repo/com/fasterxml/jackson/core/jackson-annotations/2.6.5/jackson-annotations-2.6.5.jar:/Users/zhaochangqing/Documents/idea/repo/com/fasterxml/jackson/core/jackson-core/2.6.5/jackson-core-2.6.5.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-web/4.2.5.RELEASE/spring-web-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-aop/4.2.5.RELEASE/spring-aop-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-beans/4.2.5.RELEASE/spring-beans-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-context/4.2.5.RELEASE/spring-context-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-webmvc/4.2.5.RELEASE/spring-webmvc-4.2.5.RELEASE.jar:/Users/zhaochangqing/Documents/idea/repo/org/springframework/spring-expression/4.2.5.RELEASE/spring-expression-4.2.5.RELEASE.jar com.kfit.App
objc[33486]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java (0x10139a4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x102bc04e0). One of the two will be used. Which one is undefined.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.3.RELEASE)

2019-03-20 16:12:12.356  INFO 33486 --- [           main] com.kfit.App                             : Starting App on bogon with PID 33486 (/Users/zhaochangqing/Documents/idea/temp/spring-boot/spring-boot-hello2/target/classes started by zhaochangqing in /Users/zhaochangqing/Documents/idea/MyProject/dddjava-question-bank)
2019-03-20 16:12:12.359  INFO 33486 --- [           main] com.kfit.App                             : No active profile set, falling back to default profiles: default
2019-03-20 16:12:12.415  INFO 33486 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot[email protected]8909f18: startup date [Wed Mar 20 16:12:12 CST 2019]; root of context hierarchy
2019-03-20 16:12:13.197  INFO 33486 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2019-03-20 16:12:13.809  INFO 33486 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8194 (http)
2019-03-20 16:12:13.826  INFO 33486 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2019-03-20 16:12:13.827  INFO 33486 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.32
2019-03-20 16:12:13.889  INFO 33486 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-03-20 16:12:13.890  INFO 33486 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1475 ms
2019-03-20 16:12:14.131  INFO 33486 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'myServlet1' to [/myServlet1/*]
2019-03-20 16:12:14.132  INFO 33486 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-20 16:12:14.133  INFO 33486 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'com.kfit.servlet.MyServlet2' to [/myServlet2/*]
2019-03-20 16:12:14.135  INFO 33486 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-03-20 16:12:14.135  INFO 33486 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-03-20 16:12:14.136  INFO 33486 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2019-03-20 16:12:14.136  INFO 33486 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2019-03-20 16:12:14.136  INFO 33486 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'myFilter' to urls: [/*]
MyServletContextListener ServletContex初始化
过滤器初始化
2019-03-20 16:12:14.429  INFO 33486 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot[email protected]8909f18: startup date [Wed Mar 20 16:12:12 CST 2019]; root of context hierarchy
2019-03-20 16:12:14.476  INFO 33486 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/world/{name}]}" onto public java.lang.String com.kfit.controller.DemoController.word(java.lang.String)
2019-03-20 16:12:14.477  INFO 33486 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello]}" onto public java.lang.String com.kfit.controller.DemoController.hello()
2019-03-20 16:12:14.479  INFO 33486 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2019-03-20 16:12:14.479  INFO 33486 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-03-20 16:12:14.496  INFO 33486 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-03-20 16:12:14.496  INFO 33486 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-03-20 16:12:14.521  INFO 33486 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-03-20 16:12:14.599  INFO 33486 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2019-03-20 16:12:14.675  INFO 33486 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8194 (http)
2019-03-20 16:12:14.681  INFO 33486 --- [           main] com.kfit.App                             : Started App in 2.8 seconds (JVM running for 3.518)

http://localhost:8194/hello    
MyServletRequestListener 初始化
2019-03-20 16:12:21.687  INFO 33486 --- [0.1-8194-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-03-20 16:12:21.687  INFO 33486 --- [0.1-8194-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2019-03-20 16:12:21.701  INFO 33486 --- [0.1-8194-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 14 ms
执行过滤操作
>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
进入hello
>>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
MyServletRequestListener 销毁
MyServletRequestListener 初始化
执行过滤操作
MyServletRequestListener 销毁

http://localhost:8194/ 
MyServletRequestListener 初始化
执行过滤操作
>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
MyServletRequestListener 销毁

MyServletRequestListener 初始化
执行过滤操作
MyServletRequestListener 销毁

http://localhost:8194/myServlet2/ 
MyServletRequestListener 初始化
执行过滤操作
>>>>>>>>>>doGet()<<<<<<<<<<<
>>>>>>>>>>doPost()<<<<<<<<<<<
MyServletRequestListener 销毁

MyServletRequestListener 初始化
执行过滤操作
MyServletRequestListener 销毁

2019-03-20 16:18:40.117  INFO 33486 --- [       Thread-7] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot[email protected]8909f18: startup date [Wed Mar 20 16:12:12 CST 2019]; root of context hierarchy
2019-03-20 16:18:40.139  INFO 33486 --- [       Thread-7] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
过滤器销毁
MyServletContextListener ServletContex销毁

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

里面有不少有意思的点,比如运行命令就添加了很多idea的jar包
我们主要关注一下几个点,日志我进行了提取:

第一个例子

MyServletContextListener ServletContex初始化
过滤器初始化

listener初始化竟然在过滤器之前,虽然是实现了context,就因为实现了context,才先初始化。
然后没一次请求来了 MyServletRequestListener listener都初始化一遍。最后都会销毁

http://localhost:8194/hello    
MyServletRequestListener 初始化
2019-03-20 16:12:21.687  INFO 33486 --- [0.1-8194-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-03-20 16:12:21.687  INFO 33486 --- [0.1-8194-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2019-03-20 16:12:21.701  INFO 33486 --- [0.1-8194-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 14 ms
执行过滤操作
>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
进入hello
>>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
MyServletRequestListener 销毁
MyServletRequestListener 初始化
执行过滤操作
MyServletRequestListener 销毁

第一个请求是一个controller请求
然后首先是listener初始化,然后过滤,然后执行interceptor,然后方法,最后执行的是销毁listener操作,那么为什么过滤器会执行力两次呢?
debug返现是favorite.ico又请求了一次。。。

第二个例子

http://localhost:8194/ 
MyServletRequestListener 初始化
执行过滤操作
>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)
>>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
>>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
MyServletRequestListener 销毁

这个是不存在的资源,没什么区别

第三个例子

http://localhost:8194/myServlet2/ 
MyServletRequestListener 初始化
执行过滤操作
>>>>>>>>>>doGet()<<<<<<<<<<<
>>>>>>>>>>doPost()<<<<<<<<<<<
MyServletRequestListener 销毁

请求的是一个servlet,所以就没有走interceptor

自己的结论

关闭服务器的时候,才会销毁过滤器和listener
如果listener实现了context,他的初始化顺序会在filter之前,然后每次请求,对应的listener都会初始化,然后销毁
然后正常的顺序是

listener初始化-filter初始化-filter过滤-listener过滤-servlet-interceptor-aop-controller了

DispatcherServlet 可以认为是请求分发器,在每次来请求的时候,都会来处理,在listener之后执行。白话理解:监听到了一个请求,然后分发有对应的类来处理。执行顺序按照 分发器-过滤器-监听器-拦截器-aop-controller 记忆(监听器)

至于初始化顺序,就跟踪代码了。

其他点:
因为没有用到seesion,所以session listener一直没有初始化,而且他不是context的。。。

知识点2

一带而过
Filter与Interceptor联系与区别

  1. 拦截器是基于java的反射机制,使用代理模式,而过滤器是基于函数回调。
  2. 拦截器不依赖servlet容器,过滤器依赖于servlet容器。
  3. 拦截器只能对action起作用,而过滤器可以对几乎所有的请求起作用(可以保护资源)。
  4. 拦截器可以访问action上下文,堆栈里面的对象,而过滤器不可以。

57886709302fcba18495b2534556c3ab

参考

todo

  • 容器的支持点
  • 具体远离
Spread the love

转载请注明链接地址: » spring-过滤器,servlet,监听器,拦截器,aop

赞 (0) 请我喝杯瑞幸咖啡

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏