首页 > 文章列表 > SpringBoot怎么使用Interceptor拦截器

SpringBoot怎么使用Interceptor拦截器

springboot interceptor
102 2023-05-15

SpringBoot怎么使用Interceptor拦截器

在springboot中使用拦截器也比较简单,实现HandlerInterceptor或者AsyncHandlerInterceptor接口,再从配置里添加一下拦截器就完成了;

AsyncHandlerInterceptor接口继承了HandlerInterceptor,多了一个afterConcurrentHandlingStarted方法:

接口里的方法:

  • preHandle:在Controller之前执行,可以判断参数,执行的controller方法等,返回值为boolean,返回true继续往下运行(下面的拦截器和controller),否则开始返回操作(执行之前的拦截器返回等操作);

  • postHandle:在Controller之后,视图返回前执行,可对ModelAndView进行处理再返回;

  • afterCompletion:请求完成后执行;

  • afterConcurrentHandlingStarted:controller返回值是java.util.concurrent.Callable时才会调用该方法并使用新线程运行;

方法执行顺序有两种:

  • preHandle -> 执行Controller -> postHandle -> afterCompletion;

  • preHandle -> 执行Controller -> afterConcurrentHandlingStarted -> callable线程执行call()方法 -> 新线程开始preHandle -> postHandle -> afterCompletion;(controller方法返回Callable对象时)

配置拦截器:

实现WebMvcConfigurer接口里的addInterceptors方法,使用参数InterceptorRegistry对象添加自己的拦截器,可以添加指定拦截路径或者去掉某些过滤路径,还可以设置拦截器的优先级order,优先级由小到大,默认0;

多个拦截器的执行顺序:

preHandle方法按照order由小到大顺序,执行完controller后,其他方法则反向顺序,跟过滤器Filter类似;

测试启动类,默认配置:

/**

 * 2023年3月16日下午4:56:23

 */

package testspringboot.test9interceptor;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

/**

 * @author XWF

 *

 */

@SpringBootApplication

public class Test9Main {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        SpringApplication.run(Test9Main.class, args);

    }

 

}

controller类:

/**

 * 2023年3月16日下午4:58:02

 */

package testspringboot.test9interceptor;

 

import java.util.concurrent.Callable;

 

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

/**

 * @author XWF

 *

 */

@RestController

@RequestMapping("/interceptor")

public class Test9Controller {

 

    @RequestMapping("/a")

    public String a(String s) {

        System.out.println(">>>a():" + s);

        return "OK";

    }

    

    @RequestMapping("/b")

    public Callable<String> b() {

        Callable<String> callable = new Callable<String>() {

            @Override

            public String call() throws Exception {

                Thread.sleep(2000);

                System.out.println("call() thread id=" + Thread.currentThread().getId());

                Thread.sleep(2000);

                return "abcdefg";

            }

        };

        System.out.println(">>>b()");

        return callable;

    }

    

}

两个自定义拦截器1和2:

/**

 * 2023年3月16日下午5:14:14

 */

package testspringboot.test9interceptor;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

/**

 * @author XWF

 *

 */

public class MyInterceptor1 implements HandlerInterceptor {

 

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        System.out.println("preHandle 1, handler=" + handler);

        return request.getQueryString().length() < 10 ? true : false; 

    }

    

    @Override

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

            ModelAndView modelAndView) throws Exception {

        System.out.println("postHandle 1");

    }

    

    @Override

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

            throws Exception {

        System.out.println("afterCompletion 1");

    }

    

}
/**

 * 2023年3月16日下午5:15:28

 */

package testspringboot.test9interceptor;

 

import java.util.Date;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.AsyncHandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

/**

 * @author XWF

 *

 */

@Component

public class MyInterceptor2 implements AsyncHandlerInterceptor {

 

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        System.out.println("preHandle 2 " + new Date() + " ThreadId=" + Thread.currentThread().getId());

        return true;

    }

    

    @Override

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

            ModelAndView modelAndView) throws Exception {

        System.out.println("postHandle 2");

    }

    

    @Override

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

            throws Exception {

        System.out.println("afterCompletion 2");

    }

    

    @Override

    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        System.out.println("afterConcurrentHandlingStarted 2 " + new Date());

    }

    

}

配置拦截器:

/**

 * 2023年3月16日下午5:20:31

 */

package testspringboot.test9interceptor;

 

import javax.annotation.Resource;

 

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

 

/**

 * @author XWF

 *

 */

@Configuration

public class MyInterceptorConfig implements WebMvcConfigurer {

 

    @Resource

    MyInterceptor2 myinterceptor2;

    

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new MyInterceptor1())

            .addPathPatterns("/interceptor/a")        //添加拦截路径,两种参数List<String>和String ...

            .excludePathPatterns("/interceptor/b")        //排除路径,两种参数List<String>和String ...

            .order(1);        //设置拦截器顺序,由小到大,默认0

        registry.addInterceptor(myinterceptor2);    //也可以使用spring管理的对象

    }

    

}

发送一个post测试请求:http://192.168.1.30:8080/interceptor/a?s=hello,拦截器2的order默认0,拦截器1的order为1,preHandle先执行2的,controller执行之后,剩下的Handle都是先执行1再执行2的;

发送preHandle返回false的请求:http://192.168.1.30:8080/interceptor/a?s=hello123456789,拦截器1的preHandle返回false后,直接执行2的afterCompletion;

发送测试callable的请求:http://192.168.1.30:8080/interceptor/b?s=hello,拦截路径配置跳过拦截器1只执行拦截器2,通过threadid可以看到前后使用的是两个线程;