Hi I’m Shendi
SpringBoot拦截器的使用
简介
最近要实现一个全局对象的传递,在接口中直接通过增加函数参数来直接使用的这种方式
之前一直使用的是过滤器,但这种需求过滤器是没有办法实现的,过滤器可以给请求注入字符串,但不能注入对象
例如 User 类,想要的效果如下
public String test(User user) {
return user.toString();
}
经过使用,拦截器也不能实现这样的效果…
可以使用addArgumentResolvers来实现,参考 https://sdpro.top/blog/html/article/1047.html
SpringBoot拦截器和Servlet的过滤器类似,相当于基于AOP的函数拦截,拦截器可以用来进行身份验证、日志记录、请求参数处理等。
创建拦截器
有两种方法
- 实现 org.springframework.web.servlet.HandlerInterceptor
- 继承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter
- 这个我用的时候已经被标记弃用了,并且我看实现的AsyncHandlerInterceptor接口,而AsyncHandlerInterceptor实现HandlerInterceptor,所以建议使用第一种
接口代码如下
可以看到接口定义了三个默认行为,分别为如下
名称 | 描述 |
---|---|
preHandle | 在请求处理前执行,可以理解为过滤器的 chain.doFilter 上面部分代码,有一个boolean返回值,返回true则会继续执行,否则不继续执行 |
postHandle | 在请求处理完执行,可以理解为过滤器的 chain.doFilter 后面部分代码 |
afterCompletion | 处理完执行,在postHandle之后。可以理解为finally |
代码如下
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class DefaultIntercept implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("pre");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("post");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("after");
}
}
配置拦截器
要使拦截器生效,还需要进行以下操作
- 创建类,实现WebMvcConfigurer接口
- 实现addInterceptors函数
- 在函数内使用 registry.addInterceptor 来使拦截器生效
例如
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(defaultIntercept()).addPathPatterns("/**");
}
@Bean
public DefaultIntercept defaultIntercept() {
return new DefaultIntercept();
}
}
后面的 addPathPatterns
为匹配的规则,具体可以参考文档,/**
就代表全部
运行测试
随便建个接口,试试拦截器效果
@GetMapping("/")
public String get() {
System.out.println("接口执行");
return "test";
}
请求后控制台输出如下
在pre的时候 return false
看一下结果
可以看到执行了pre后就没有继续执行了
调整优先级
在配置类,添加拦截器的时候可以使用 order
函数指定
registry.addInterceptor(defaultIntercept()).addPathPatterns("/**").order(1);
值越小,优先级越高,不配置默认是0,如果没有指定,那么将按照加入的先后顺序进行拦截
END