Interceptor和Filter对比
Filter是作用在Servlet前。Interceptor执行在controller前。所以正确的处理流程是
Filter前处理 --> Interceptor前处理 --> controller--> Interceptor后处理 --> Filter后处理
对比
Filter接口定义在Javax.servlet包中 | 接口HandlerInterceptor定义在org.springframework.web.servlet包中。 | 所在包不同 |
Filter在Servlet前后起作用,Filters通常将请求和相应当做黑盒,Filter通常不考虑servlet的实现 | 拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期,在请求过程中获取信息,Interceptor 通常和请求更加耦合。 | 在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现 |
Filter 是 Servlet 规范规定的。 | 而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。 | 使用范围不同 |
Filter是Servlet规范中定义的,是Servlet容器支持的 | 拦截器在Spring容器内,由Spring进行管理 | 规范不同 |
Filter不能够使用Spring容器资源 | 拦截器是Spring的组件,归Spring管理,配置在Spring文件中,因此可以使用Spring里的任何资源,对象等 | Spring中使用Interceptor更加容易 |
Filter是被Server(tomcat etc)调用 | Interceptor是被Spring调用 | Filter总是优先于Intreceptor执行 |
HandlerInterceptor (拦截器)参考:https://blog.csdn.net/yb546822612/article/details/102950040
SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。
在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式:
第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;
第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
1、preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。
2、postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。
3、afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
Interceptor实现
1、定义Interceptor
@Component
public class RequestResultinterceptorFilter implements HandlerInterceptor {
private static final String RESPONSE_REQUEST_ANN = "RESPONSE_REQUEST_ANN";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//请求的方法
if (handler instanceof HandlerMethod) {
final HandlerMethod handlerMethod = (HandlerMethod) handler;
final Class<?> clazz = handlerMethod.getBeanType();
final Method method = handlerMethod.getMethod();
//请求方法的类是否有自定义注解
if (clazz.isAnnotationPresent(MyResponseResult.class)) {
//设置请求体,包装向下传递,ResponseBodyAdvice实现
request.setAttribute(RESPONSE_REQUEST_ANN, clazz.getAnnotation(MyResponseResult.class));
} else if (method.isAnnotationPresent(MyResponseResult.class)) {
request.setAttribute(RESPONSE_REQUEST_ANN, method.getAnnotation(MyResponseResult.class));
}
}
return true;
}
//其他方法可不实现
}
2、注册自定义拦截器
@Configuration
public class MyWebAppConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RequestResultinterceptorFilter()).addPathPatterns("/**");
}
}