0%

SpringBoot项目实战之HandlerInterceptorAdapter实现自定义拦截器

SpringBoot中提供了HandlerInterceptorAdapter适配器供我们自定义拦截器,可以拦截自定义或所有的请求做相应的处理。

HandlerInterceptorAdapter中共有四个方法:

  • preHandle :在Controller方法被调用前执行
  • postHandle :在Controller方法调用后执行
  • afterCompletion :在整个请求处理完成之后执行
  • afterConcurrentHandlingStarted :用来处理异步请求,当Controller中有异步请求方法的时候会触发该方法。

实现步骤

自定义拦截器

继承HandlerInterceptorAdapter,重写方法(在实际项目中,可以按照实际的业务重写方法,不需要重写全部四个方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @Author zhangting
* @Desc 自定义拦截器
* @Date 2020/08/04
**/
@Component
@Slf4j
public class MyInterceptor1 extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- preHandle(1) -----");
return super.preHandle(request, response, handler);
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("----- postHandle(1) -----");
super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("----- afterCompletion(1) -----");
super.afterCompletion(request, response, handler, ex);
}

@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- afterConcurrentHandlingStarted(1) -----");
super.afterConcurrentHandlingStarted(request, response, handler);
}
}

注册拦截器

实现WebMvcConfigurer,注册拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @Author zhangting
* @Desc 注册拦截器
* @Date 2020/08/04
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

@Autowired
private MyInterceptor1 myInterceptor1;


@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor1);
}
}

上面实现的是自定义一个拦截器的情景,但是一般在实际项目中会需要自定义多个拦截器,那么这些拦截器的执行顺序又是如何确定的呢?拦截器内部的方法的执行顺序又是怎样的呢?

自定义多个拦截器

定义MyInterceptor2拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @Author zhangting
* @Desc 自定义拦截器
* @Date 2020/08/04
**/
@Component
@Slf4j
public class MyInterceptor2 extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- preHandle(2) -----");
return super.preHandle(request, response, handler);
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("----- postHandle(2) -----");
super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("----- afterCompletion(2) -----");
super.afterCompletion(request, response, handler, ex);
}

@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- afterConcurrentHandlingStarted(2) -----");
super.afterConcurrentHandlingStarted(request, response, handler);
}
}

将自定义的MyInterceptor2拦截器注册到容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @Author zhangting
* @Desc 注册拦截器
* @Date 2020/08/04
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

@Autowired
private MyInterceptor1 myInterceptor1;

@Autowired
private MyInterceptor2 myInterceptor2;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor1);
registry.addInterceptor(myInterceptor2);
}
}

此时我们定义了两个拦截器,且注册的时候,先注册MyInterceptor1拦截器,再注册MyInterceptor2拦截器,接下来测试一下他们的执行顺序。

使用postman模拟请求,打印日志


结论

由测试结果可以得出:

  • 拦截器的执行顺序_按照注册顺序_。
  • 方法的执行顺序按照:preHandle()方法按照正序执行,postHandle()、afterCompletion()方法按照倒序执行。

自定义拦截URL

在注册拦截器如果不指定拦截的URL则默认所有的URL都会被拦截。我们也可以在注册拦截器时自定义该拦截器需要拦截的URL。

使用postman模拟请求,查看日志: