在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 b() {Callable callable = new Callable() {@Overridepublic 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("preHandle 1, handler=" + handler);return request.getQueryString().length() < 10 ? true : false; }@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("postHandle 1");}@Overridepublic 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("preHandle 2 " + new Date() + " ThreadId=" + Thread.currentThread().getId());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("postHandle 2");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("afterCompletion 2");}@Overridepublic 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 {@ResourceMyInterceptor2 myinterceptor2;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/interceptor/a") //添加拦截路径,两种参数List和String ....excludePathPatterns("/interceptor/b") //排除路径,两种参数List和String ....order(1); //设置拦截器顺序,由小到大,默认0registry.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可以看到前后使用的是两个线程;
上一篇:js学习10(面向对象)
下一篇:底层原理计划--RocketMq