所有controller interceptor_filter、interceptor、aspect不知如何选择

a659cf6b17c4299a68aa43137b585bf2.png

前言

小伙伴们应该听说过过滤器、拦截器、切面,印象上都能够起到截断拦截的作用,在做一些业务需求时,不知道如何选择,今天老顾就来介绍一下他们之间的区别。

Filter过滤器

过滤器可以拦截到方法的请求和响应(ServletRequest request, ServletResponse response),并对请求响应做出过滤操作。

过滤器依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,一个过滤器实例只能在容器初始化时调用一次。

使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。话不多说,先上代码cc215c5a3a18b80f4d0c04fc56f2f388.png再定义两个Controller,一个UserController,一个OrderController76dc649f9826fb77a67d44fe146ae347.pnga739d6a75492cf9fdd49a2a489afa5d4.png虽然Filter过滤器和Controller请求都已经定义了,但现在过滤器是不起作用的。需要把Filter配置一下,有两个方案第一个方案在Filter上面加上@Component

@Component

public class TimeFilter implements Filter

第二个方案配置化注册过滤器4c84a107481efdf9e3e44a9006b199f1.png第二个方案的特点就是可以细化到过滤哪些规则的URL我们来启动应用时,过滤器被初始化了,init函数被回调aa15f45941deedaeff3374cbb4e4778f.png

请求http://localhost:9000/order/1

e92c001687e3b530a33004262c41eb7b.png看看控制台的日志输出98ac8c10a935c902320351e62e06f055.png

请求http://localhost:9000/user/1

0aefec59e55f8b568315c07821dddb15.png控制台日志输出c26e5f975036e679e290ac7bc72aba90.png停止应用后,控制台输出0d963e1c8d0336c657612d53edea366e.pngFilter随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。

1.启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;2.每一次请求时都只调用方法doFilter()进行处理;3.停止服务器时调用destroy()方法,销毁实例。

我们再来看看doFilter方法

doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

从参数我们看到,filter里面是能够获取到请求的参数和响应的数据;但此方法是无法知道是哪一个Controller类中的哪个方法被执行。还有一点需要注意的是,filter中是没法使用注入的bean的,也就是无法使用@Autowired9244fef6d0802dcef38dc8394c6d5d9f.png上面代码注入的值为null。这是为什么呢

其实Spring中,web应用启动的顺序是:listener->filter->servlet,先初始化listener,然后再来就filter的初始化,再接着才到我们的dispathServlet的初始化,因此,当我们需要在filter里注入一个注解的bean时,就会注入失败,因为filter初始化时,注解的bean还没初始化,没法注入。

如果一定你要使用,需要做一些处理,可以私信老顾哦

Interceptor拦截器

依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在一个方法前,调用一个方法,或者在方法后,调用一个方法。ed41146c9f822676ca9838925d762e05.png在WebMvcConfigurationSupport配置一下60445d4f384ba61a722860606510804b.png执行结果4b79ec4213cc11eac9ca62bb217d8772.png我们发现拦截器中可以获取到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)f10006868247461017f090b173c8d178.pngapplyPreHandle这个方法执行,就是执行的拦截器的preHandler方法,但这个过程中,controller方法没有从request中获取请求参数,组装方法参数;而是在ha.handle这个方法的时候,才会组装参数

虽然没法得到方法的参数,但是可以获得IOC的bean哦。

再说明一点的是postHandler方法

postHandler方法的执行,当controller内部有异常,posthandler方法是不会执行的。

afterCompletion方法,不管controller内部是否有异常,都会执行此方法;此方法还会有个Exception ex这个参数;如果有异常,ex会有异常值;没有异常 此值为null

注意点如果controller内部有异常,但异常被@ControllerAdvice 异常统一捕获的话,ex也会为null

Aspect切片

AOP操作可以对操作进行横向的拦截,最大的优势在于他可以获取执行方法的参数,对方法进行统一的处理。常见使用日志,事务,请求参数安全验证ead4a80a4e2b6c5463df2d0bb5c16cd0.png上面的代码中,我们是可以获取方法的参数的a4ac6fa950a295036d7b6d7ba79332da.png虽然切面aop可以拿到方法参数,但拿不到response,request对象。

总结

我们这里来总结一下过滤器、拦截器、Aspect,看看区别b675aa96adc3ef1a87886be070de0775.png如果三者方式同时采用,那他们的执行顺序是什么呢?

filter -> interceptor -> ControllerAdvice -> aspect -> controller

返回值顺序,或异常返回顺序

controller -> aspect -> controllerAdvice -> Interceptor -> Filter

11958e201c13dcd2bbd635c4aecccf74.png用一个图描述一下执行顺序abc76b9b30d51ed0d943c96e90c99ef7.png小伙伴们可以根据自身业务,和上面技术的各自特点,去选择相应的技术。今天老顾就介绍到这里,谢谢!!!

后台回复【4】加入享学课堂粉丝交流群,相亲交友,技术交流

推荐阅读:

Redis 下购物车设计实战

Lambda表达式入门(下篇)

Lambda表达式入门(上篇)

就知道你 “在看”d2132ae232abe6a260c5e32dc40c4a6b.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值