今天查了一下spirng中三种action前处理业务的三种方法过滤器、拦截器和切面的执行顺序记录一下。
三者的区别:
1、过滤器filter
过滤器是服务端的一个组件,是基于servlet实现从客户端访问服务端web资源的一种拦截机制,对请求request和响应response都进行过滤,依赖于serverlet容器,使用时,实现Filter接口,在web.xml里配置对应的class还有mapping-url
filter里面初始方法为3个,init()、doFilter()、destroy()。三个方法分别为对拦截数据进行预处理的初始化方法、实际进行业务处理的doFilter方法、和销毁方法destroy。
业务流程图如下:
2、拦截器interceptor
拦截器,顾名思义,它的作用就是拦截,这个要和过滤器区分开,过滤器依赖serverlet容器,获取request和response处理,是基于函数回调(框架本身调用的,它会遍历所有注册的过滤器,并且一一调用doFilter()),简单说就是“去取你想取的”。
拦截器是通过Java反射机制来拦截web请求,是“拒你想拒绝的”,它只拦截web请求,但不拦截静态资源。
拦截器,在AOP中用于在某个方法或字段被访问之前,进行拦截,然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
@Component
public class TimeInterceptor implements HandlerInterceptor {
// 在controller调用之前调用,通过返回true或者false决定是否进入Controller层
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandle");
System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
System.out.println(((HandlerMethod)handler).getMethod().getName());
request.setAttribute("startTime", new Date().getTime());
return true;
}
// 在请求进入控制层之后调用,但是在处理请求抛出异常时不会调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long start = (Long)request.getAttribute("startTime");
System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));
}
// 在请求处理完成之后,也就是在DispatherServlet渲染了视图之后执行,也就是说这个方法必定是执行,包含异常信息,它的主要作用就是清理资源
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion");
Long start = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));
System.out.println("ex is "+ex);
}
}
流程图如下图所示:
3、aop切面
相比过滤器,拦截器能够知道用户发出的请求最终被哪个控制器处理,但是拦截器还有一个明显的不足,即不能够获取request的参数以及控制器处理之后的response。
(注意 ,只能通过request.getParameter(..)来获取)所以就有了切片的用武之地了。
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.wtzhou.security.controller.UserController.*(..))")
// @After("")
// @Before("")
// @AfterThrowing()
// @AfterReturning()
public Object handlerControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
out.println("请求参数为:"+arg);
}
out.println("TimeAspect 切片开始执行");
long start = currentTimeMillis();
Object proceed = proceedingJoinPoint.proceed();
out.println("切片执行耗时:" + (currentTimeMillis() - start));
out.println("切片执行结束!");
return proceed;
}
}
总结
【Filter与Interceptor的区别】
- filter基于filter接口中的doFilter回调函数,interceptor则基于Java本身的反射机制;
- filter是依赖于servlet容器的,没有servlet容器就无法回调doFilter方法,而interceptor与servlet无关;
- filter的过滤范围比interceptor大,filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而interceptor只能过滤请求,只对action起作用,在action之前开始,在action完成后结束(如被拦截,不执行action);
- 在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用一次。
【Interceptor 与spring AOP的区别】
- spring Interceptor也是一种aop思想,文中的spring AOP主要是讲aop应用,interceptor 的使用场合比aop小很多,顾名思义,它是拦截一些action请求,但是比aop使用起来简便;
- 程序执行的顺序是先进过滤器,再进拦截器,最后进切面;
- Interceptor可以阻止代码执行下去,当preHandle返回false,那么这个请求就到此结束,真正的被拦截了,但是aop不能,它只是单纯的切入添加操作;
以上部分内容来自简书:
作者:不知名的蛋挞
链接:https://www.jianshu.com/p/2d1fa2834d9c