Filter和Interceptor和Aspect
Filter过滤器
过滤器可以拦截到方法的请求和响应(ServletRequest request, ServletResponse response),并对请求响应做出过滤操作。
过滤器 依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,一个过滤器实例只能在 容器初始化时调用一次。
使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。
Filter随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。
1.启动服务器时加载过滤器的实例,并 调用init()方法来初始化实例;
2.每一次请求时都 只调用方法doFilter()进行处理;
3.停止服务器时 调用destroy()方法,销毁实例。
我们再来看看doFilter方法
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
从参数我们看到,filter里面是能够获取到请求的参数和响应的数据;但此方法是无法知道是哪一个Controller类中的哪个方法被执行。还有一点需要注意的是,filter中是没法使用注入的bean的,也就是无法使用@Autowired。
其实Spring中,web应用启动的顺序是:listener->filter->servlet,先初始化listener,然后再来就filter的初始化,再接着才到我们的dispathServlet的初始化,因此,当我们需要在filter里注入一个注解的bean时,就会注入失败,因为filter初始化时,注解的bean还没初始化,没法注入。
Interceptor拦截器
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在一个方法前,调用一个方法,或者在方法后,调用一个方法。
applyPreHandle这个方法执行,就是执行的拦截器的preHandler方法,但这个过程中,controller方法没有从request中获取请求参数,组装方法参数;而是在ha.handle这个方法的时候,才会组装参数。
虽然没法得到方法的参数,但是可以获得IOC的bean哦。
再说明一点的是postHandler方法。
postHandler方法的执行,当controller内部有异常,posthandler方法是不会执行的。
afterCompletion方法,不管controller内部是否有异常,都会执行此方法;此方法还会有个Exception ex这个参数;如果有异常,ex会有异常值;没有异常 此值为null。
注意点如果controller内部有异常,但异常被@ControllerAdvice 异常统一捕获的话,ex也会为null
Aspect切片
AOP操作可以对操作进行横向的拦截,最大的优势在于他可以获取执行方法的参数,对方法进行统一的处理。常见使用日志,事务,请求参数安全验证等。虽然切面aop可以拿到方法参数,但拿不到response,request对象。
如果三者方式同时采用,那他们的执行顺序是什么呢?
filter -> interceptor -> ControllerAdvice -> aspect -> controller