springmvc拦截器

实现拦截器步骤

步骤一   声明拦截器类(实现 handlerInterceptor接口)

1.主要看prehandle方法的返回值确定是否放行,如果是true,表示放行,会执行该拦截器的prehandle方法,

如果有多个拦截器,且全部放行  则preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行

2.如果是false表示不放行。只执行该拦截器的prehandle方法

    如果有多个拦截器,某一个不放行则所有拦截器的posthandle一个都不执行,aftercomplitiation倒序执行

   举例:有四个拦截器 ,第三个拦截之后没有放行, 就是执行第一个拦截器的prehandle,第二个拦截器的prehandle,第三个拦截器的prehandle, 第二个拦截器的afterCompletion  第一个拦截器的afterCompletion      所有的postHandle方法都不执行

package com.testfilter;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AInterceptor  implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("prehandle方法执行了");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle方法执行了");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion方法执行了");
    }
}

 步骤二  在springmvc.xml中配置

mvc:exclude-mapping设置不拦截的路径

如果访问不拦截的路径,则不会执行拦截器的任何一个方法

 注意:拦截器中的路径 ,/**代表拦截所有路径,/*代表只是一层目录

    /*  可以拦截

      /* 不能拦截 

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/index" />
            <bean class="com.testfilter.AInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

二.拦截后跳转至指定页面

比如拦截所有不是login的请求,并且查看session中是否有用户信息,没有就跳转到登录界面,有就放行,

注意:跳转一定要跳转至不被拦截的请求路径上,否则会一直循环下去 :

-请求被拦截  ----重定向或者请求转发至页面 -----重定向请求或请求转发请求被拦截--请求被拦截

而且返回值一定是false,如果是true,请求转发或重定向一个页面,拦截器放行一个页面,服务器会不知道该显示哪个页面

package com.example.springbootdemo3.testfilter;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

//1.设置拦截器实现handlerinterceptor接口,写拦截方法
public class firstInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入了拦截器");
        HttpSession session = request.getSession();
        if (session.getAttribute("user") == null) {
            System.out.println("拦截器跳转了");
            response.sendRedirect("index");
        }
        return false;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("posthandel执行了");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("afterhandle执行了");
    }
}

2、拦截器的三个抽象方法

SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法

postHandle:控制器方法执行之后执行postHandle()

afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation()

3、多个拦截器的执行顺序

a>若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

在前面的会先执行

assecondinterceptor先于后面的bfirstINterceptor

 <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.testfilter.AsecondInterceptor"></bean>

            <!--            <mvc:exclude-mapping path="/testRequestEntity"/>-->
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.testfilter.BfirstInterceptor"></bean>

preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行

为什么posthandle 和aftercomplation会返序执行呢(如下图)?观察源码

4.错误页面 

当拦截器不拦截时(prehandel返回值为true),如果请求发生了错误,则会通过两次拦截器。

因为顺序是这样的:

请求到达拦截器 --拦截器放行--页面发生错误

--请求转发错误的提示页面--拦截器放行

就是显示错误页面的请求会被拦截一次。未避免这种情况, 可以设置不拦截  /error请求

<mvc:exclude-mapping path="/error"/>

错误的提示页面指的是 

 

观察源码:

在控制方法中打断点 可以发现下面方法栈中有disparctureservlet,证明disparctureserlvet是先于return 这句执行的,或者说由disparctureservlet控制这个return返回(是不是不对啊?要问问)

在dispratctureservlet 的 mav 方法前是 prehandle方法 之后是posthandle 在之后渲染视图时执行 aftercomplitation 在这几个方法分别打断点

 鼠标移动到prehandle 的 mappedHandler

进入这个方法

这个方法遍历了三个拦截器,如果拦截器都不进行拦截(即所有prehandle方法中返回值都为true),则什么都不做,最后返回true 。 interceptorindex就是 最后一个拦截器的编号 (编号从0开始) 。

继续f8 在执行完mv= 之后 进入posthandle方法,发现这里是将interceptorList 倒过来,减减遍历

继续f8 进入aftercomapplication方法,发现这里也是将interceptorList 倒过来,减减遍历

所以 prehandle方法 posthandle方法是倒序调用的

b>若某个拦截器的preHandle()返回了false

如果有拦截器进行了拦截,则立刻返回false,并且interceptorIndex为 上一个拦截器对应的编号。

再看源码可以发现,posthandle一个都不执行,aftercomplitiation倒序执行

总结:有四个拦截器 ,第三个拦截之后没有放行, 就是执行第一个拦截器的prehandle,第二个拦截器的prehandle,第三个拦截器的prehandle, 

 第二个拦截器的afterCompletion         第一个拦截器的afterCompletion

所有的postHandle方法都不执行

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值