拦截器和过滤器执行顺序:
init -> doFilter -> servlet -> preInterceptor -> controller -> postInterceptor -> destroy
区别:
- 过滤器基于函数回调实现,拦截器基于java反射机制(动态代理)
- filter依赖于servlet,需要容器,比如Tomcat,只能使用在web中,interceptor是spring一个组件,spring容器管理,使用spring的地方就可以使用interceptor
- 执行顺序,filter使用@Order规定顺序,intercetpor根据注册顺序
- 拦截器要使用IOC容器中的东西需要在配置加入拦截器之前手动@Bean注入拦截器
Filter
容器启动时执行init方法
容器摧毁时执行destroy方法
对于每个请求执行doFilter方法
可以有多个过滤器,request和response交给filterChain传递给下一个filter
使用@Order定义过滤器执行顺序
filter接口的一个实现为OncePerRequestFilter,每个请求执行一次过滤
HandlerInterceptor
controller之前执行preHandle
controller之后执行postHandle
afterCompletion在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行
每个方法如果返回false表示终止这个请求,流程到此结束
拦截器需要注册到IOC容器中,WebMvcConfigurer接口的实现中加入
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
AOP
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* cn.redarm.springboottest.controller.*.*(..))")
public void doPointcut(){}
@Before("doPointcut()")
public void recordLog(JoinPoint joinPoint){
System.out.println("joinPoint.getArgs() = " + joinPoint.getArgs());
System.out.println("joinPoint.getSignature().getName() = " + joinPoint.getSignature().getName());
}
}
自定义注解拦截
注解:
@Inherited
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLogAnnotation {
String logContent() default "默认value";
}
拦截器:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
Method method = ((HandlerMethod) handler).getMethod();
// 如果方法带有MyLogAnnotation注解
if (AnnotatedElementUtils.isAnnotated(method, MyLogAnnotation.class)) {
MyLogAnnotation myAnnotation = method.getAnnotation(MyLogAnnotation.class);
if (myAnnotation == null) {
return true;
}
//获取注解的参数
String logContent = myAnnotation.logContent();
System.out.println("logContent = " + logContent);
return true;
}
}
return true;
}
注册拦截器:
registry.addInterceptor(new MyLogAnnotationInterceptor()).addPathPatterns("/**");