spring 切点拦截 获取类名 spring 拦截器获取返回的结果

admin2024-06-01  18

 

拦截器的概述:

拦截器是SpringMVC中的一个核心应用组件,主要用于处理多个

Controller的共性问题.当我们的请求由DispatcherServlet派发

到具体Controller之前首先要执行拦截器中一些相关方法,在这些

方法中可以对请求进行相应预处理(例如权限检测,参数验证),这些方法可以决定对这个请求进行拦截还是放行.

 

>>服务器一启动,就会创建拦截器对象,

>>对拦截器配置延迟加载是没有用的

>>拦截器是单例的,整个过程,拦截器只有一个实例对象

 

 

拦截器需要实现 HandleInterceptor接口,或者继承HandlerInterceptorAdaptor抽象类;

HandlerInterceptor接口的三个方法:

1,preHandle()
2,postHandle()
3,afterCompletion()

 

拦截器的执行过程:

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_maven,第1张

 

详解:当页面的request请求发送过来,由前端控制器DispatcherServlet来控制,交给对应的Controller进行请求的处理,但是在处理之前,要先经过拦截器的拦截(如果配置了的话),在由对应controller处理之前,先执行对应的

 

1,preHandle()是拦截器最先执行的方法,是在请求到达Controller之前执行的,其实就是拦截器用于拦截请求的,

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_拦截器_02,第2张

三个参数,分别是request,response,handelr就是这个请求要去找的后端处理器Controller.方法的返回值是bloolean类型,如果返回为false,就说明请求在此终结,不能执行后面的代码了.如果返回值为true,那么这个拦截器就要放行,将请求交给后端处理器Controller.

2. postHandler

这个方法,是在后端控制器controller处理完请求之后,就执行的,这个方法,多了一个参数,ModelAndView

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_Inter_03,第3张

后端控制器controller处理请求可能需要返回页面和数据,所以会多一个ModelAndView,但是这个方法,是在渲染页面之前执行的,渲染热面是交个前端控制器来完成的.

3.afterCompletion:拦截器最后执行的方法,

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_spring 切点拦截 获取类名_04,第4张

 

拦截器在spring-configs.xml的配置:

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_Inter_05,第5张

或者使用注解的方式,

在拦截器上添加@Service注解,

那么就不用使用bean,使用ref引用就行;

 

 

 

>>>>拦截器链:

当我们系统中有多个拦截器时,这些拦截器可以构成一个拦截器链.其原理类似过滤器中的过滤链。在多个拦截器应用中仅当所有匹配的拦截器的preHandle()都执行之后,才会调用Controller中处理请求的方法,然后再执行所有匹配的拦截器的postHandler(),再执行所有匹配的拦截器的afterCompletion()。

在拦截器链中,各拦截器的执行先后顺序取决于配置文件中配置的节点的先后顺序!

 

 

 

 

拦截器的执行顺序:(假设都能放行)

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_Inter_06,第6张

 

 

拦截器链的配置:

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_Inter_07,第7张

线程安全问题:

场景:假设需要做一个记录方法执行的时间的拦截器,

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_springMVC_08,第8张

在cntroller处理请求之前,要进入这个事件拦截器的preHandler方法,这个时候,会记录一下当前的时间作为startTime,当请求处理完毕,视图渲染结束之后,再取得一次系统时间作为方法运行结束的时间,由于跨了方法,所以strtTime必须定义成全局变量,否则afterCompletion方法拿不到这个startTime变量.

 

但是这是就会存在线程安全问题:

 

出现线程安全问题的前提条件:

1) 多个线程并发执行;

2) 多个线程存在共享数据

3) 多个线程对共享数据的操作不是原子操作.

 

这个事件拦截器是单例的,但是可能需要处理多个请求,startTime定义在全局变量,那么这个数据就是共享的,

 

spring 切点拦截 获取类名 spring 拦截器获取返回的结果,spring 切点拦截 获取类名 spring 拦截器获取返回的结果_拦截器_09,第9张

当请求1需要打印所用时间是,但是得到的startTime不是这个请求对应的startTime,可能是其他线程更改了之后的时间.

 

 

 

对于这种情况,最好是不要使用共享数据,将数据都存在单独的request域中

然后需要用到这个数据时,就从自己的request域中拿这个数据,那么这样就不会出现线程安全问题.

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!