listener、filter、servlet、interceptor在springboot中执行顺序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了listener、filter、servlet、interceptor在springboot中执行顺序相关的知识,希望对你有一定的参考价值。

参考技术A 本地访问 http://localhost:8080/my ,查看日志信息,如下:

执行顺序如下:
1.项目 run 时, filter 开始 init
2.浏览器发送 get 请求, listener 开始 init
3. filter 执行 doFilter 方法
4. servlet 执行 doGet 方法
5. interceptor 开始依次执行 preHandle 、 postHandle 、 afterCompletion 方法
6. listener 执行 requestDestroyed 方法, get 请求结束
7.项目 down 掉, filter 执行 destroy 方法

filter,servlet,listener,interceptor

在SpringBootApplication上使用@ServletComponentScan注解后,

Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。

过滤器

默认使用的4个

在启动打印出来的日志里有:

  • Filter ‘requestContextFilter‘ configured for use

  • Filter ‘hiddenHttpMethodFilter‘ configured for use

  • Filter ‘characterEncodingFilter‘ configured for use

  • Filter ‘formContentFilter‘ configured for use

 

优先级

低位值意味着更高的优先级。自定义Filter,避免和默认的Filter优先级一样,不然会冲突。

 

作用(使用场景)

  • 比如用户验证。

  • 如果涉及页面跳转,filter就不适合 前后端分离的情况。

 

实例

启动类 加上 注解

@ServletComponentScan

 

 

自定义的filter

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(urlPatterns = "/api/*")
public class LoginFilter implements Filter 

    /**
     * 容器加载的时候调用
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        System.out.println("init loginFilter");
    

    /**
     * 请求被拦截的时候进行调用
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException 
        System.out.println("doFilter loginFilter");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String username = request.getParameter("username");
        if ("xdclass".equals(username)) 
            filterChain.doFilter(request, response);
        else 
            response.sendRedirect("/index.html");    // 重定向
        
    

    @Override
    public void destroy() 
        System.out.println("destroy loginFilter");
    

 

 

测试

添加controller的访问方法。

@GetMapping(value="/api/v1/account")
public Object account()
    params.put("money", "1000");
    return params;

 

 

访问  http://localhost:8080/api/v1/account?username=xdclass


"money": "1000"

 

测试通过。

 

自定义servlet

例子

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/v1/api/test/customs", name = "userServlet")
public class UserServlet extends HttpServlet 

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        resp.getWriter().print("custom sevlet");
        resp.getWriter().flush();
        resp.getWriter().close();
    

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        this.doGet(req, resp);
    

 

启动类 加上 @ServletComponentScan , 和 过滤器的使用 很像。

 

监听器

自定义Listener(常用的监听器 servletContextListener、httpSessionListener、servletRequestListener)。

@WebListener
public class RequestListener implements ServletRequestListener 

    @Override
    public void requestDestroyed(ServletRequestEvent sre) 
        // TODO Auto-generated method stub
       System.out.println("======requestDestroyed========");
    

    @Override
    public void requestInitialized(ServletRequestEvent sre) 
     System.out.println("======requestInitialized========");
   、

 

 

 

拦截器

1、老方法,jdk8之前

继承 WebMvcConfigurerAdapter


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



@Configuration
public class CustomOldWebMvcConfigurer extends WebMvcConfigurerAdapter


@Override
public void addInterceptors(InterceptorRegistry registry)


registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/");

super.addInterceptors(registry);

 

 

 

2、jdk8之后的新方法

使用 implements WebMvcConfigurer

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

@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer

@Override
public void addInterceptors(InterceptorRegistry registry)
registry.addInterceptor(new LoginIntercepter())
.addPathPatterns("/api/login/**");
WebMvcConfigurer.super.addInterceptors(registry);

 

 

3、以上添加了拦截器,现在 给出自定义的拦截器。

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);
    
    
    

 

小结

  • 是基于函数回调 doFilter(),而Interceptor则是基于AOP思想。

  • Filter在只在Servlet前后起作用,而Interceptor能够深入到方法前后、异常抛出前后等。

  • 依赖于Servlet容器即web应用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境。

  • 在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。

  • Filter和Interceptor的执行顺序 过滤前->拦截前->action执行->拦截后->过滤后。

 

 

 

 

 

 

以上是关于listener、filter、servlet、interceptor在springboot中执行顺序的主要内容,如果未能解决你的问题,请参考以下文章

filter,servlet,listener,interceptor

sprintboot 整合Servlet,Filter,Listener

SpringBoot中使用Servlet,Filter,Listener

springBoot:web开发-Servlets, Filters, listeners

Springboot - -web应用开发-Servlets, Filters, listeners

Filter,Servlet,Listener区别与联系