SpringMVC的拦截器,你知道多少?

前言

springmvc的拦截器是基于aop思想实现和应用的,我们可以在某个方法甚至是字段被访问前进行拦截,加上我们想要执行的操作,非侵入式地添加上我们想要加入的功能和校验。拦截器也是我们学习springmvc所必须要掌握的一个知识点,本文将从拦截器的快速入门和应用进行介绍。

一、拦截器的接口方法介绍

要定义拦截器,需要先实现HandlerInterceptor接口,我们进入到这个接口中,可以看到里面一共只有三个方法


  • preHandle 对接收到的请求进行前置处理,如果返回true才将请求放行给controller。如果返回false,则中断请求。
  • postHandle 执行controller后,渲染视图之前调用
  • afterCompletion 该方法在整个请求结束之后执行,当然前提依然是 preHandle方法的返回值为 true 才行。该方法一般用于资源清理工作

二、自定义自己的拦截器

定义拦截器的方法只需要实现上面的HandlerInterceptor接口即可

package com.xiaoming.util;

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

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

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 对接收到的请求进行前置处理,如果返回true才将请求放行给controller
     *  如果返回false,执行中断请求
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle has done...");
        return true;
    }


    /**
     *  执行croller后,渲染视图之前调用
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle has done...");
    }
    /*
      整个请求结束后执行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion has done...");
    }
}

在spring-mvc.xml文件中配置

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.xiaoming.util.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
package com.xiaoming.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class TargetController {

    @RequestMapping("/sayHi")
    public ModelAndView sayHi() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("name", "小明");
        modelAndView.setViewName("index");
        return modelAndView;
    }

}

Controller.java

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello,${name}</title>
</head>
<body>
<h2>Hello,${name}</h2>
</body>
</html>

index.jsp

三、拦截器的执行顺序

在上个入门案例的基础上,我们新建一个拦截器,不同之处在于拦截器2的preHandle方法返回值是false,不进行放行

package com.xiaoming.util;

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

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

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 对接收到的请求进行前置处理,如果返回true才将请求放行给controller
     *  如果返回false,执行中断请求
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle222 has done...");
        return false;
    }


    /**
     *  执行croller后,渲染视图之前调用
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle222 has done...");
    }
    /*
      整个请求结束后执行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion222 has done...");
    }
}

第二个拦截器

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.xiaoming.util.MyInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--对哪些资源执行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.xiaoming.util.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

spring-mvc.xml
将项目部署到tomcat后,访问http://localhost:8088/sayHi
控制台输出如下:


我们可以看到,两个拦截器的preHandle方法都正常执行了。
那么为什么postHandle方法没有执行呢?
因为拦截器2返回值为false,所以请求被拦截,无法到达controller,两个类的postHandle方法都不需要执行。
那么afterCompletion方法为什么被调用了呢?
这里的话我们要了解afterCompletion的调用时机,这个方法是在请求结束后调用的,preHandle不放行,请求自然就结束中断了,也就会执行拦截器的afterCompletion方法。
那么为什么只调用了拦截器1的afterCompletion方法呢?
是因为afterCompletion方法的执行还有一个前提,该拦截器的preHandle方法返回值为true。所以这里的话afterCompletion方法只调用了一次。

在实际项目开发中,我们常常使用拦截器来进行用户登录校验,如果用户已经登录则返回true放行,如果用户没有登录,则跳转到登录页面

posted @ 2020-10-25 16:54  moutory  阅读(8)  评论(0编辑  收藏  举报  来源