Spring MVC 之拦截器

一、拦截器的配置

  • SpringMVC 中的拦截器用于拦截控制器方法的执行
  • SpringMVC 中的拦截器需要实现 HandlerInterceptor

1、创建 FirstInterceptor

package com.example.mvc.interceptor;

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

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

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");
    }
}

2、springMVC.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <!--自动扫描包-->
    <context:component-scan base-package="com.example.mvc"></context:component-scan>

    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <mvc:interceptors>
        <bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
    </mvc:interceptors>
</beans>

3、controller

package com.example.mvc.controller;

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

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

4、结果

-------------->FirstInterceptor:preHandle
-------------->FirstInterceptor:postHandle
-------------->FirstInterceptor:afterCompletion

FirstInterceptor 中的 preHandle 方法的返回值改为 false,执行结果为:

-------------->FirstInterceptor:preHandle

仅执行了 preHandle,postHandle,afterCompletion 两个方法未执行。

5、总结
SpringMVC 中的拦截器有三个抽象方法:

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

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

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

二、SpringMVC 拦截器的几种配置方式

1、第一种配置方式

<mvc:interceptors>
    <bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>

或者

<bean id="firstInterceptor" class="com.example.mvc.interceptor.FirstInterceptor"></bean>

<mvc:interceptors>
    <ref bean="firstInterceptor"></ref>
</mvc:interceptors>

以上两种配置方式都是对 DispatcherServlet 所处理的所有的请求进行拦截。

2、第二种配置方式

<bean id="firstInterceptor" class="com.example.mvc.interceptor.FirstInterceptor"></bean>
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"></mvc:mapping>
        <mvc:exclude-mapping path="/test/index"></mvc:exclude-mapping>
        <ref bean="firstInterceptor"></ref>
    </mvc:interceptor>
</mvc:interceptors>

以上配置方式可以通过 ref 或 bean 标签设置拦截器,通过 mvc:mapping 设置需要拦截的请求,通过 mvc:exclude-mapping 设置需要排除的请求,即不需要拦截的请求。

验证

FirstInteceptor.java
注意 preHandle 方法的返回值应当为 false

package com.example.mvc.interceptor;

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

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

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("-------------->FirstInterceptor:preHandle");
        return false;
    }

    @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");
    }
}

创建两个Controller
(1)TestController

package com.example.mvc.controller;

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

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

(2)InterceptorController

package com.example.mvc.controller;

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

@Controller
@RequestMapping("/interceptor")
public class InterceptorController {

    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

启动服务,分别访问 localhost:8080/springmvc/test/index 以及 localhost:8080/springmvc/interceptor/index,会发现第一个路径可以正常访问,第二个路径则被拦截。

三、多个拦截器执行顺序

1、创建 SecondInterceptor.java

package com.example.mvc.interceptor;

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

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

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");
    }
}

2、springMVC.xml 中拦截器的配置

<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>

<mvc:interceptors>
    <bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
    <ref bean="secondInterceptor"></ref>
</mvc:interceptors>

访问 localhost:8080/springmvc/test/index ,输出结果如下:

-------------->FirstInterceptor:preHandle
-------------->SecondInterceptor:preHandle
-------------->SecondInterceptor:postHandle
-------------->FirstInterceptor:postHandle
-------------->SecondInterceptor:afterCompletion
-------------->FirstInterceptor:afterCompletion

3、调整 springMVC.xml 文件中拦截器的配置顺序

<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>

<mvc:interceptors>
    <ref bean="secondInterceptor"></ref>
    <bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>

访问 localhost:8080/springmvc/test/index ,输出结果如下:

-------------->SecondInterceptor:preHandle
-------------->FirstInterceptor:preHandle
-------------->FirstInterceptor:postHandle
-------------->SecondInterceptor:postHandle
-------------->FirstInterceptor:afterCompletion
-------------->SecondInterceptor:afterCompletion

4、将 SecondInterceptor.java 中的 preHandler() 方法返回值改为 false,FirstInterceptor.java 中的 preHandle() 方法返回值改为 true。

springMVC.xml 文件中拦截器的配置如下:

<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>

<mvc:interceptors>
    <bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
    <ref bean="secondInterceptor"></ref>
</mvc:interceptors>

访问 localhost:8080/springmvc/test/index ,输出结果如下:

-------------->FirstInterceptor:preHandle
-------------->SecondInterceptor:preHandle
-------------->FirstInterceptor:afterCompletion

4、总结

  • 若每个拦截器的 preHandle() 都返回 true,此时多个拦截器的执行顺序和拦截器在 SpringMVC 的配置文件的配置顺序有关,preHandle() 会按照配置的顺序执行,而 postHandle() 和 afterCompletion() 会按照配置的反序执行。
  • 若某个拦截器的 preHandle() 返回了 false,preHandle() 返回 false 和它之前的拦截器的 preHandle() 都会执行,postHandle() 都不执行,返回 false 的拦截器之前的拦截器的 afterCompletion() 会执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值