大家好,又见面了,我是你们的朋友全栈君。
SpringMvc—拦截器
作用
拦截器是用来拦截经过dispatcherServlet【请求控制器】的请求。它用来拦截控制器方法的执行。
拦截器通过实现接口HandlerInterceptor并在SpringMvc配置文件中添加配置实现拦截功能。记得为拦截器类加注解把它加到IOC容器中
使用
在拦截器中
首先添加注解,@Component【既不是bean、也不是service、也不是controller,是一个基本java类,所以用它声明,用别的也行】,然后实现接口HandlerInterceptor,实现三个方法
@Component public class FirstInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor--preHandle--控制器方法执行之前执行"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor--postHandle---控制器方法执行之后执行"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor---afterCompletion----视图渲染完毕执行"); } }
在SpringMvc配置文件中
首先添加命名空间mvc、context,开启组件扫描、添加视图解析器thymeleaf、开启mvc注解扫描。
配置文件中的标签的作用注释里都有
<mvc:interceptors> <!--使用bean标签注册的拦截器会对经过dispatcherServlet的所有请求进行处理,使用ref也是一样的--> <!-- <bean class="xlw.com.SpringMvc03.Interceptor.FirstInterceptor"></bean>--> <!-- <ref bean="firstInterceptor"></ref>--> <!-- <mvc:interceptor>--> <!--使用标签mvc:interceptor可以规定那些请求被拦截哪些不被拦截,可以设置多个,最后要对拦截器注册--> <!-- <mvc:mapping path="/test?"/>--> <!-- <mvc:exclude-mapping path="/"/>--> <!-- <mvc:exclude-mapping path="/test1"/>--> <!-- <ref bean="firstInterceptor"></ref>--> <!-- </mvc:interceptor>--> <ref bean="firstInterceptor"></ref> <ref bean="secondInterceptor"></ref> </mvc:interceptors>
多个拦截器(preHandle返回true)
在上面的配置文件中配置两个拦截器,在对请求进行拦截时可以发现方法的执行顺序 有些不同
@Component public class SecondInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("SecondInterceptor--preHandle--控制器方法执行之前执行"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("SecondInterceptor--postHandle---控制器方法执行之后执行"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("SecondInterceptor---afterCompletion----视图渲染完毕执行"); } }
拦截器处理请求后结果
可以发现,preHandle执行顺序是跟在配置文件的先后注册顺序执行的,postHandle和AfterCompletion是反过来执行的
FirstInterceptor--preHandle--控制器方法执行之前执行
SecondInterceptor--preHandle--控制器方法执行之前执行
SecondInterceptor--postHandle---控制器方法执行之后执行
FirstInterceptor--postHandle---控制器方法执行之后执行
SecondInterceptor---afterCompletion----视图渲染完毕执行
FirstInterceptor---afterCompletion----视图渲染完毕执行
在源码中
首先为控制器方法打上断点。debug启动服务器,进入断点模式,然后再debug底下的控制台执行方法找到DispatchServlet的1061,点进去,做好以下断点。
再对断点放行,再次请求资源。开始观察。
第一个断电对应的正是preHandle方法,在if的判断条件中,发现需要一个true的返回值,与感叹号一起使判断条件变成false,才能使程序继续往下执行,否则就会终结当前循环
点击下一行进入applyPreHandle方法具体执行中,发现有一个++的for循环,里面循环执行一个Interceptor的list数组,可以看见list里面正是SpringMvc自己的interceptor和我自己注册的interceptor,++执行就确保了PreHandle方法按照在配置文件中的顺序执行。
在for循环中的if判断,就是判断返回值是不是false,如果是就会执行当前的afterCompletion方法【就是最后执行的那个方法】,并且返回false终结掉DispatcherServlet中的程序执行。如果返回的是true,就会按照在list中的顺序执行
preHandel执行完后会跳到下一个断点,就是那个mv那一行,进行获取视图名称。再跳到下一个断点就会回到控制器方法,在跳到下一个断点就是那个postHandel方法。
来到postHandel的哪一行断点,点击下一行,进入postHandel,发现是一个–的for循环,循环的依旧是那个interceptor的list集合,所以就能知道为什么postHandel的执行顺序和配置文件中的相反。afterCompletion方法的执行也和这个postHandel一样–for循环
多个拦截器(preHandel返回false)
依旧是断点模式,但是是将preHandel返回值变成false。就会发现,在进入applyPreHandel方法中后,先执行第一个注册的interceptor的preHandel方法,执行后再执行第二个拦截器,但是第二个拦截器的返回值被修改为false,就会通过applyPreHandel的for循环中的if判断,中执行第一个interceptor的triggerAfterCompletion并返回false。
再回到Dispatch Servlet中就会通过if判断,执行return,后面的就不执行了。请求被拦截。
所以在有多个interceptor被注册后,其中有一个interceptor的preHandel方法的返回值为false,那么在这个拦截器之前注册的拦截器的preHandel方法和afterCompletion方法都会执行,这个拦截器的preHandel方法也会执行。post Handel方法都不执行
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/154784.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...