小伙伴们应该听说过 过滤器、拦截器、切面 ,印象上都 能够起到截断拦截的作用 ,在做一些业务需求时, 不知道如何选择 ,今天老顾就来介绍一下他们之间的区别。
过滤器可以 拦截到方法的请求和响应 (ServletRequest request, ServletResponse response),并对 请求响应 做出过滤操作。
过滤器 依赖于servlet容器 。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,一个过滤器实例只能在 容器初始化时调用一次。
使用过滤器的目的是用来 做一些过滤操作 ,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在 过滤器中修改HttpServletRequest的一些参数 ,包括:过滤低俗文字、危险字符等。
话不多说,先上代码
再定义两个Controller,一个UserController,一个OrderController
虽然Filter过滤器和Controller请求都已经定义了,但现在过滤器是不起作用的。需要把Filter配置一下,有两个方案
@Component public class TimeFilter implements Filter
第二个方案的特点就是可以 细化到过滤哪些规则的URL
看看控制台的日志输出
控制台日志输出
停止应用后,控制台输出
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还没初始化,没法注入。
如果一定你要使用,需要做一些处理,可以私信老顾哦
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上, 基于Java的反射机制,属于面向切面编程(AOP)的一种运用 ,就是在一个方法前,调用一个方法,或者在方法后,调用一个方法。
在WebMvcConfigurationSupport配置一下
执行结果
我们发现拦截器中可以获取到Controller对象
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
object handler就是controller方法对象
HandlerMethod handlerMethod = (HandlerMethod)handler; handlerMethod.getBean().getClass().getName(); //获取类名 handlerMethod.getMethod().getName(); //获取方法名
但我们发现获取不到方法的参数值,这个是为什么呢?在 DispatcherServlet类 中,方法
doDispatch(HttpServletRequest request, HttpServletResponse response)
applyPreHandle这个方法执行,就是执行的拦截器的preHandler方法,但这个过程中,controller方法没有从request中获取请求参数,组装方法参数; 而是在ha.handle这个方法的时候,才会组装参数
虽然没法得到方法的参数,但是可以获得IOC的bean哦。
再说明一点的是 postHandler方法
postHandler方法的执行,当controller内部有异常,posthandler方法是不会执行的。
afterCompletion方法,不管controller内部是否有异常,都会执行此方法;此方法还会有个Exception ex这个参数; 如果有异常,ex会有异常值;没有异常 此值为null
注意点如果controller内部有异常,但异常被@ControllerAdvice 异常统一捕获的话,ex也会为null
AOP操作可以对操作进行横向的拦截,最大的优势在于他可以 获取执行方法的参数 ,对方法进行统一的处理。常见 使用日志,事务,请求参数安全验证 等
上面的代码中,我们是可以获取方法的参数的
虽然切面aop可以拿到方法参数,但拿不到response,request对象。
我们这里来总结一下过滤器、拦截器、Aspect,看看区别
如果三者方式同时采用,那他们的 执行顺序是什么 呢?
filter -> interceptor -> ControllerAdvice -> aspect -> controller
controller -> aspect -> controllerAdvice -> Interceptor -> Filter
用一个图描述一下执行顺序
小伙伴们可以根据自身业务,和上面技术的各自特点,去选择相应的技术。今天老顾就介绍到这里,谢谢!!!