想要了解拦截器在Servlet的声明周期的时间点 请查看:
Spring 拦截器(Interceptors)是Spring MVC框架的一部分,它提供了一种机制,允许你在请求到达Controller之前和响应返回给客户端之后进行处理。拦截器可以被用于多种场景,如日志记录、权限检查、事务管理等。
工作原理
Spring 拦截器基于Java Servlet的Filter接口实现。当一个请求被发送到Spring MVC应用时,它会通过一系列的拦截器,然后到达目标的Controller。Controller处理完请求后,响应也会通过这些拦截器返回给客户端。
拦截器链(Interceptor Chain)是由多个拦截器组成的,它们的执行顺序取决于它们在Spring配置中的声明顺序。
拦截器的主要方法
Spring 定义了HandlerInterceptor
接口,它包含了三个主要的回调方法:
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
:- 这个方法在Controller处理请求之前被调用。
- 如果这个方法返回
true
,处理流程将继续;如果返回false
,处理流程将停止,不会调用后续的拦截器和Controller。
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
:- 这个方法在Controller处理请求之后,DispatcherServlet进行视图渲染之前被调用。
- 可以通过修改
ModelAndView
来影响视图的渲染。
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
:- 这个方法在整个请求处理完毕,也就是视图渲染完毕之后被调用。
- 可以用来进行资源清理。
当一个请求被拦截时,它会通过一系列的拦截器。每个拦截器都有机会决定是否要放行请求、处理请求或者是中止请求。如果一个拦截器决定中止请求,后续的拦截器将不会被调用。
在Spring中,拦截器链的执行依赖于每个拦截器的preHandle
方法的返回值。如果preHandle
返回true
,则请求继续传递到下一个拦截器或者最终的处理器。如果preHandle
返回false
,则请求处理流程中断。
定义拦截器
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: zanglikun
* @Date: 2022/5/7 18:43
* @Description: 拦截器,实现HandlerInterceptor,然后重写方法
*/
@Slf4j
@Component // 可省略,但需要注册到WebMvcConfigurer
public class MyInterceptor implements HandlerInterceptor {
/**
* handler 参数的类型可以是以下几种:更多用于操作反射
* HandlerMethod:代表一个控制器方法,包含方法的相关信息,如方法名、参数等。
* HandlerInterceptor:代表一个拦截器,可以在请求处理前、处理后或渲染视图时执行一些操作。
* ResourceHttpRequestHandler:代表一个处理静态资源的处理器,可以处理静态文件的请求。
* WebSocketHandler:代表一个 WebSocket 处理器,用于处理 WebSocket 相关的请求。
*/
// 请求拦截前处理
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 请求进来,会被拦截,这里可做日志打印,可获取所有请求参数。返回true 代表放行 返回false 代表拒绝请求。
return HandlerInterceptor.super.preHandle(request, response, handler);
}
// Controller已经处理完毕了
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
// 结尾工作,如果preHandle方法内部(非Controller等后续有异常哈)抛出异常,本方法将不会触发,一般不过使用此方法
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
注册自定义拦截器
【教程】:创建MVCConfig类。实现WebMvcConfigurer,重写addInterceptor()方法即可!
注意:如果注册多个拦截器没有设置Order,那么先注册的先执行!如果都设定了Order那么Order越小优先执行!Order一样,估计就是按照拦截器名字为准了或注册的顺序!
请使用:
import XXXX.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
public class MVCConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
// 不支持Jrebel热部署,需要重启服务
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册一个拦截器,并放行/user下的接口
registry.addInterceptor(loginInterceptor).order(0)
.excludePathPatterns(
"/user/**",
"/.............."
);
}
}
请废弃(经过投产使用时:发现@Value、@Resource 不可用)
原因:一开始我以为是低版本的Springboot版本导致的,经过测验,在实现WebMvcConfigurer的addInterceptors方法的时候,没有使用Sping创建的Bean管理,而是new出来的,肯定不会有@Value、@Resource注入的值!(浪费我好多时间)
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 MVCConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册一个拦截器,并放行/user下的接口
registry.addInterceptor(new MyInterceptor()).excludePathPatterns("/user/**").order(0);
}
}
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤