16 SpringMVC 拦截器 方法详解 和 多拦截器

补充:

interceptor 的执行顺序大致为:

1.请求到达 DispatcherServlet
2.DispatcherServlet 发送至 Interceptor ,执行 preHandle
3.请求达到 Controller,返回视图前执行 postHandle
4.请求结束后,postHandle 执行

 

先看下 刚刚拿三个重写的方法(特征已经说了 这里不说)

   @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }



 

第一个是preHandle 他有三个参数 ,都是我们学过最基本的 请求、响应,至于第三个 handler ,我也不知道 我百度了一下:

handler,是指controller的@Controller注解下的"完整"方法名, 是包含exception等字段信息的.  emmm...用的不多

其实呢 preHandle这个方法 主要还是用来判断用户有无权限 或 参数是否正确,这个方法是用的最多的 ,因为每一次请求都要结果他: 下面演示 不合格拦截后跳转到index(或者其他页面):

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String Parameter = request.getParameter("init");
        //如果携带参数 init 且 init = yes 的话 那么就放行 不然就转发(或者其他)到index(视图解析器已配置)
        if ("yes".equals(Parameter)){
            return true;
        }else{
            request.getRequestDispatcher("/index.jsp").forward(request,response);
        }
        return false;
    }

 


 

第二个方法 的参数 是第一个一样的 再加一个 ModelAndView ,如果你控制器的方法里 有modelandview 你完全可以吧你携带出去的数据 在这里做更改,但是没必要 ,因为你本来就要带出去还改他干嘛...

测试一下:

控制器方法:(modelandview (这里是分离的 我懒得写,都一样的)已携带 data

    @RequestMapping("/show")
   public String show(Model model){
    model.addAttribute("data","成功返回 未被拦截!");    //已携带data
    return "TestJSP";
    }

 

拦截器postHandle方法:

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //控制器方法那里携带了参数 data ,这里替换掉。
        modelAndView.addObject("data","成功执行 已替换参数 未拦截!");
    }

 

允许结果:

 


 

第三个方法没什么好说的  ,前两个是请求和响应,第三个是 Handler 第四个是异常  这个几乎不怎么用。。。。

暂缺

 


多拦截器

我们在声明拦截器的时候 是用  <mvc:interceptors> 然后下面的  <mvc:interceptor>  标签来声明,一个拦截器可以设置拦截指定的控制器 网址。

因为可以配置多个拦截器 所以呢,如果我配置了多个拦截器 而且 这些拦截器拦截的网址一样的话 那么他有个过滤器执行的先后顺序

 

比如现在我有两个拦截器 两个一个  MyHandlerInterceptor 一个是 MyHandlerInterceptor2 ,那么使他们都拦截同一个网址 show :

 

拦截器:

package com.bihu;

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

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

public class MyHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是拦截器的preHandle方法 我执行了!");
        return true;    //测试先后顺序 放行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("我是拦截器的postHandle方法 我执行了!");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("我是拦截器的afterCompletion方法 我执行了!");

    }
}

 

拦截器2:

 

package com.bihu;

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

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

public class MyHandlerInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是拦截器的preHandle2方法 我执行了!");
        return true;    //测试先后顺序 放行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("我是拦截器的postHandle2方法 我执行了!");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("我是拦截器的afterCompletion2方法 我执行了!");

    }
}

 

然后 拦截器配置(声明):

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.bihu.MyHandlerInterceptor"></bean>
    </mvc:interceptor>

    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.bihu.MyHandlerInterceptor2"></bean>
    </mvc:interceptor>
</mvc:interceptors>

注意啊 连个拦截器都拦截全部的请求(url)

然后我们直接测试一下 看下打印结果:

我是拦截器的preHandle方法 我执行了!
我是拦截器的preHandle2方法 我执行了!
我是拦截器的postHandle2方法 我执行了!
我是拦截器的postHandle方法 我执行了!
我是拦截器的afterCompletion2方法 我执行了!
我是拦截器的afterCompletion方法 我执行了!

可以看到 先执行了 :

拦截器的 pre  ==》拦截器2的pre   ===》

拦截器2的post ==》 拦截器的 post ==》

拦截器2 的 after ==》拦截器的 after ==》结束

 

其实我们还记得firter过滤器吗,他执行的顺序是在web.xml中定义的顺序,那么其实springmvc也是,至于为什么post方法哪里 拦截器2先执行 是因为 类似于弹栈 (个人觉得 总之顺序就是这样),

我把他们配置的顺序调换一下:

<mvc:interceptors>

    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.bihu.MyHandlerInterceptor2"></bean>
    </mvc:interceptor> 
    
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.bihu.MyHandlerInterceptor"></bean>
    </mvc:interceptor>

</mvc:interceptors>

执行结果:

我是拦截器的preHandle2方法 我执行了!
我是拦截器的preHandle方法 我执行了!
我是拦截器的postHandle方法 我执行了!
我是拦截器的postHandle2方法 我执行了!
我是拦截器的afterCompletion方法 我执行了!
我是拦截器的afterCompletion2方法 我执行了!

呐  总之顺序就是这样



 

摘抄CSDN博主 这瓜保熟么  链接:https://blog.csdn.net/luzhensmart/article/details/86702671

那么拦截器和过滤器有什么区别:

(1)Filter需要在web.xml中配置,依赖于Servlet;
(2)Interceptor需要在SpringMVC中配置,依赖于框架;
(3)Filter的执行顺序在Interceptor之前,具体的流程见下图;

两者的本质区别:拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。

 

posted @ 2021-07-15 13:31  咸瑜  阅读(306)  评论(0编辑  收藏  举报