SpringMVC拦截器的执行过程

SpringMVC拦截器的执行过程

在开发一个网站的过程可能有这样的需求:某些页面只希望几个特定的用户浏览,对于这样的访问权限维护,应该如何实现呢?拦截器就可以实现这样的需求。
SpringMVC的拦截器于Java Servlet的过滤器类似,它主要用于拦截用户请求并做出相应的处理,通常应用在权限验证,记录请求信息的记录,判断是否登录等功能。
拦截器的内容需要掌握:1拦截器的定义;2-拦截器的配置;3-拦截器的执行流程。
1-拦截器的定义。
在SpringMVC框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:一种是通过实现HandlerInterceptor接口或继承HandlerInterceptor接口的实现类来定义;另一种是通过实现WebRequestInterceptor接口或者继承WebRequestInterceptor接口的实现类。

定义完拦截器后,需要在SpringMVC的配置文件中配置拦截器,mvn:interceptors元素用于配置一组拦截器,其子元素bean配置一个全局拦截器,拦截所有请求,mvn:interceptor定义指定路径的拦截器,其子元素mvn:mapping用于配置拦截器作用的路径,该路径在其属性path中定义,path的属性值/**表示拦截所有路径,/goTest表示拦截以/goTest结尾的路径,如果请求路径中包含不需要拦截的内容,可以使用mvc:exclude-mapping子元素进行配置。
需要注意的是:mvn:interceptor元素的子元素必须按照mvc:mapping,mvc:exclude-mapping,bean的顺序进行配置。

下面看一下拦截器的执行流程
单个拦截器的执行流程
在配置文件中如果只定义一个拦截器,程序将首先首先执行拦截器中的preHandle方法,如果该方法返回为true,程序将执行控制控制器中的请求处理方法,然后执行postHandle方法,返回视图后执行afterCompletion方法。
1-在IDEA中创建一个名为ch13-1的web应用,在WEB-INF目录下创建lib目录,将SpringMVC相关jar包复制到lib目录中,并将lib添加为库项目。

在这里插入图片描述
2-在web.xml中部署DispatcherServlet,同时配置 CharacterEncodingFilter解决中文乱码问题。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         id = "WebApp_ID" version="4.0">
    <!--部署DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/springmvc-servlet.xml</param-value>
        </init-param>
        <!--表示容器启动时加载的servlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--任意的请求都通过DispatcherServlet-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 配置 CharacterEncodingFilter解决中文乱码问题-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <!-- 配置编码格式为UTF-8 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

3-在src目录下创建包controller,在该包中创建控制器类InterceptorController

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

@Controller
public class InterceptorController {
    @RequestMapping("/gotoTest")
    public String toString(){
        System.out.println("正在测试拦截器,执行控制器的处理请求方法中") ;
        return "test" ; //跳转到test.jsp页面
}
}

4-定义拦截器,在src目录下创建包interceptor,在该包中创建拦截器类TestInterceptor,该类实现HandlerInterceptor接口,并重写三个接口方法。

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

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

/**
 * 定义一个拦截器,实现HandlerInterceptor接口,并重写三个接口方法
 */
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandler方法在控制器处理请求方法之前执行") ;
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandler方法在控制器的请求处理方法调用之后,解析视图之前执行") ;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion方法控制器处理请求方法执行完成之后,即视图渲染结束之后执行") ;
    }
}

5-在WEB-INF目录下创建SpringMVC配置文件,在该文件中扫描指定包,配置视图解析器,配置全局拦截器,拦截所有请求。

<?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.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--使用扫描机制,扫描控制器类-->
    <context:component-scan base-package="controller"/>
    <mvc:annotation-driven />
    <!--annotation-driven用于简化开发的配置,注解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter-->
    <!--使用resources过滤掉不需要dispatcherservlet的资源,例如静态资源,在使用resources时必须使用annotation-driven,否则resources会阻止任意控制器被调用-->

    <!--配置视图解析器-->
    <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" id = "internalResourceViewResolver">
        <!--前缀-->
        <property name = "prefix" value = "/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name = "suffix" value = ".jsp"/>
    </bean>
    <mvc:interceptors>
        <!--配置一个全局拦截器,拦截所有请求-->
        <bean class = "interceptor.TestInterceptor"/>
    </mvc:interceptors>
</beans>

6-在WEB-INF目录下创建一个test.jsp文件

<%--
  Created by IntelliJ IDEA.
  User: nuist__NJUPT
  Date: 2021/8/10
  Time: 16:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
视图
<%System.out.println("视图渲染结束。") ;%>
</body>
</html>

7-发布SpringMVC应用,运行Tomcat服务器,然后通过地址:http://localhost:8080/ch13_1_war_exploded/gotoTest测试拦截器,程序正确执行后控制台输出的结果如下:
在这里插入图片描述
多个拦截器的执行流程
在web应用中通常需要有多个拦截器同时工作,这时它们的preHandler()方法将按照配置文件中拦截器的配置顺序进行,而它们的postHandler方法和afterCompletion方法将按照配置顺序的反序执行。
1-在ch13-1应用的src目录的interceptor包创建两个拦截器Interceptor1和Interceptor2,拦截器实现HandlerInterceptor接口,并重写相应的三个方法。

Interceptor1:

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

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

public class Interceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor1 preHandle方法执行") ;
        //返回true,代表继续向下执行,返回false,代表中断后序操作
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor1 postHandler 方法执行") ;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor1 afterCompletion 方法执行") ;
    }
}

Interceptor2:

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

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

public class Interceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor2 preHandle方法执行") ;
        //返回true,代表继续向下执行,返回false,代表中断后序操作
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor2 postHandler 方法执行") ;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor2 afterCompletion 方法执行") ;
    }

}

2-配置拦截器,在springmvc-servlet.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.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--使用扫描机制,扫描控制器类-->
    <context:component-scan base-package="controller"/>
    <mvc:annotation-driven />
    <!--annotation-driven用于简化开发的配置,注解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter-->
    <!--使用resources过滤掉不需要dispatcherservlet的资源,例如静态资源,在使用resources时必须使用annotation-driven,否则resources会阻止任意控制器被调用-->

    <!--配置视图解析器-->
    <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" id = "internalResourceViewResolver">
        <!--前缀-->
        <property name = "prefix" value = "/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name = "suffix" value = ".jsp"/>
    </bean>
    <mvc:interceptors>
        <!--配置一个全局拦截器,拦截所有请求-->
        <bean class = "interceptor.TestInterceptor"/>
        <!--配置拦截器的作用路径为任意路径-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class = "interceptor.Interceptor1"/>
        </mvc:interceptor>
        <!--配置拦截器的作用 路径为以/goTest结尾的作用路径-->
        <mvc:interceptor>
            <mvc:mapping path="/goTest"/>
            <bean class = "interceptor.Interceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

3-测试多个拦截器,将ch13-1应用发布到Tomcat服务器,通过地址:http://localhost:8080/ch13_1_war_exploded/gotoTest测试多个拦截器,测试结果如下:
有多个拦截器同时工作,这时它们的preHandler()方法将按照配置文件中拦截器的配置顺序进行,而它们的postHandler方法和afterCompletion方法将按照配置顺序的反序执行。
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值