SpringMvc—拦截器「建议收藏」

SpringMvc—拦截器「建议收藏」SpringMvc拦截器作用拦截器是用来拦截经过dispatcherServlet【请求控制器】的请求。它用来拦截控制器方法的执行。拦截器通过实现接口HandlerInterceptor并在S

大家好,又见面了,我是你们的朋友全栈君。

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,才能使程序继续往下执行,否则就会终结当前循环

SpringMvc---拦截器「建议收藏」

 

 

 

点击下一行进入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循环

 

SpringMvc---拦截器「建议收藏」

 

 

 

 

SpringMvc---拦截器「建议收藏」

 

 

 

多个拦截器(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方法都不执行

 

SpringMvc---拦截器「建议收藏」

 

 

 

 

 

 SpringMvc---拦截器「建议收藏」

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/154784.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python字符串查找特定字符_神器是啥意思

    python字符串查找特定字符_神器是啥意思TheFuzz库对应的源码链接为https://github.com/seatgeek/thefuzz。需要说明的是,TheFuzz是FuzzyWuzzy的升级版本,后者在2020年后已经不再进行更新,所以请及时切换到TheFuzz库。1.安装方法2.两大模块fuzz和process2.1模块一:fuzz2.2模块二:process2.2.1process.extractOne(提取出相似度最高的选择)2.2.2process.extract(提取出相似度高的多个选择)3.实战案例

    2022年8月21日
    4
  • class和getClass()的区别

    class和getClass()的区别前几天做项目,觉得自己都开发一年多了,还没有自己封装的类,感觉真是白做了,再加上,看到自己的代码,我都不忍心看,有的时候,还需要自己去读自己写的代码,乱乱糟糟的,实在不忍心看,没办法,重现在开始吧,把自己需要的,都封装起来,用到什么的时候,在哪来用,方便,快捷首先是自己封装的基类baseActivity,不废话,直接上代码(其他的就不贴出来了,只有这个地方有错误)packagecom.d

    2022年6月15日
    41
  • vue组件系列1、弹窗

    vue组件系列1、弹窗

    2021年7月2日
    108
  • TaskScheduler.UnobservedTaskException「建议收藏」

    TaskScheduler.UnobservedTaskException「建议收藏」TaskScheduler.UnobservedTaskException+=(_,ev)=>PrintException(ev.Exception);

    2022年10月9日
    1
  • 地图慧制作地图

    地图慧制作地图

    2021年9月24日
    57
  • 防止页面url缓存中 ajax中post 请求的处理方式

    一般我们在开发中经常会用到Ajax请求,异步发送请求,然后获取我们想要的数据,在Ajax中使用Get请求数据不会有页面缓存的问题,而使用POST请求可是有时候页面会缓存我们提交的信息,导致我们发送的异步请求不能正确的返回我们想要的数据。

    2022年2月24日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号