14【SpringMVC的拦截器】

news2024/11/18 17:35:51

文章目录

  • 一、拦截器
    • 1.1 拦截器与过滤器
    • 1.2 拦截器的应用
      • 1.2.1 HandlerInterceptor接口
      • 1.2.2 拦截器的拦截规则
    • 1.3 搭建工程测试拦截器
      • 1.3.1 测试SpringMVC拦截器
      • 1.3.2 SprinMVC拦截器注意事项
    • 1.4 HandlerMethod类
    • 1.5 多个拦截器的执行顺序

一、拦截器

1.1 拦截器与过滤器

  • 过滤器

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。

  • 拦截器:

依赖于web框架。在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

1.2 拦截器的应用

1.2.1 HandlerInterceptor接口

在SpringMVC中,定义一个拦截器需要实现HandlerInterceptor接口;在该接口下有三个功能方法:

public interface HandlerInterceptor {
    
    // 进入handler之前的处理(选择是否将该请求拦截下来),返回true:放行,返回false:拦截
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    // handler方法执行完毕后执行
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
    
	// 页面(JSP等)渲染后执行
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
  • preHandle():该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;
    当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。
  • postHandle():该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
  • afterCompletion():该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

1.2.2 拦截器的拦截规则

定义好拦截器后,需要设置拦截器的拦截规则(说明资源该拦截,什么资源不拦截)

符号说明
?匹配任何一个字符
*匹配任何长度的字符
**匹配多级目录的路径

1.3 搭建工程测试拦截器

1.3.1 测试SpringMVC拦截器

  • pom.xml:
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dfbz</groupId>
    <artifactId>SpringMVC_01_Interceptor</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-api</artifactId>
            <version>8.5.71</version>
        </dependency>
    </dependencies>
</project>
  • web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--配置springmvc配置文件的位置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
  • 编写拦截器:
package com.dfbz.interceptor;

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 java.lang.invoke.MethodHandle;

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 请求执行前执行(handle执行前执行)
     *
     * @param request
     * @param response
     * @param handler: 要执行的handler(目标方法)
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("preHandle...");

        return true;
    }

    /**
     * handle执行后执行
     *
     * @param request
     * @param response
     * @param handler      :要执行的handler(目标方法)
     * @param modelAndView :handler返回的ModelAndView对象,如果目标方法没有返回ModelAndView则为null
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

    /**
     * 页面渲染后执行
     *
     * @param request
     * @param response
     * @param handler  :要执行的handler(目标方法)
     * @param ex       :解析JSP页面出现异常时的异常对象
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}
  • 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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--包扫描-->
    <context:component-scan base-package="com.dfbz"/>

    <!--开启注解驱动-->
    <mvc:annotation-driven />
    
    <!--静态资源放行-->
    <mvc:default-servlet-handler/>

    <!--拦截器配置:将我们编写的拦截器加入到SpringMVC管理的拦截器中-->
    <mvc:interceptors>

        <!--配置单个拦截器-->
        <mvc:interceptor>
            <!--
                path:拦截规则
                    ?:匹配单个字符
                    *:代表匹配任意长度的字符(只能匹配单机目录)
                    **:代表匹配任意长度的多级目录
            -->
<!--            <mvc:mapping path="/**"/>-->

            <!--代表拦截/user下的所有请求-->
            <mvc:mapping path="/user/**"/>

            <!--代表放行/user/register请求-->
            <mvc:exclude-mapping path="/user/register"/>

            <!--配置拦截器-->
            <bean class="com.dfbz.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>
  • Controller:
package com.dfbz.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RequestMapping("/user")
@RestController
public class UserController {

    @GetMapping("/login")
    public String login() {              // 进入拦截器
        System.out.println("login");
        return "login";
    }

    @GetMapping("/register")
    public String register() {           // 不进入拦截器
        System.out.println("register");
        return "register";
    }

    @GetMapping("{id}")                  // 进入拦截器
    public String findById(@PathVariable Integer id) {
        System.out.println("findById");
        return "findById: " + id;
    }

    @GetMapping
    public String findAll() {           // 进入拦截器
        System.out.println("findAll");
        return "findAll";
    }

    @GetMapping("/hello")               // 进入拦截器
    public ModelAndView hello() {
        ModelAndView mv = new ModelAndView();
        System.out.println("handler...");
        mv.setViewName("/hello.jsp");
        return mv;
    }
}
  • JSP页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>我是JSP页面哦!</h1>
<%
    System.out.println("页面渲染!");
%>
</body>
</html>

启动服务器,访问:

http://localhost:8080/user/register(放行)

http://localhost:8080/user/login(拦截)

http://localhost:8080/user/hello(拦截)

http://localhost:8080/user(拦截)

在这里插入图片描述

Tips:我们说的拦截指的是发送的请求会进入SpringMVC的拦截器,具体是否能访问到目标资源要看拦截器是否放行;

1.3.2 SprinMVC拦截器注意事项

1)即使访问的资源不存在,只要符合SpringMVC的拦截器规则,都会进入SpringMVC

  • 如:http://localhost:8080/user/abc 这样的请求也是会经过SpringMVC拦截器的

在这里插入图片描述

Tips:由于请求没有找到对应的资源,因此不会经过拦截器的postHandler方法

2)只要是符合SpringMVC的拦截器规则都会进入SpringMVC,静态资源也不例外!

在webapp目录下新建/js/test.js

在这里插入图片描述

在springmvc.xml中添加配置:

<mvc:interceptor>
    <mvc:mapping path="/js/**"/>
</mvc:interceptor>

访问:http://localhost:8080/js/test.js

在这里插入图片描述

同理,缺省servlet放行方式,资源连SpringMVC都没有进入,更加不会进入SpringMVC的拦截器了;

缺省servlet依赖:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>8.5.41</version>
    <scope>provided</scope>
</dependency>
  • 相关配置:
<!--代表以js后缀结尾的任何请求进入Tomcat默认的Servlet处理(放行)-->
<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>

再次访问:http://localhost:8080/js/test.js,发现资源能够直接访问,并且没有经过SpringMVC拦截器;

1.4 HandlerMethod类

HandlerMethod类是SpringMVC用于封装目标方法的类,可以通过该类获取目标方法的一系列参数,如目标方法对象、目标方法所在的类、目标方法参数、目标方法返回值等;

package com.dfbz.interceptor;

import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method;

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 请求执行前执行(handle执行前执行)
     *
     * @param request
     * @param response
     * @param handler: 要执行的handler(目标方法)
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...");

        // 转换为Handler对象
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        // 获取目标方法
        Method method = handlerMethod.getMethod();

        // 获取Controller
        Object bean = handlerMethod.getBean();

        // 获取目标方法上的形参
        MethodParameter[] methodParameters = handlerMethod.getMethodParameters();

        // 获取目标方法的返回值
        MethodParameter returnType = handlerMethod.getReturnType();

        return true;
    }
}

访问:http://localhost:8080/user/login

在这里插入图片描述

1.5 多个拦截器的执行顺序

SpringMVC多个拦截器执行流程如下:

在这里插入图片描述

编写另一个拦截器:

package com.dfbz.interceptor;

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;

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 请求执行前执行(handle执行前执行)
     *
     * @param request
     * @param response
     * @param handler: 要执行的handler(目标方法)
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("preHandle2...");
        return true;
    }

    /**
     * handle执行后执行
     *
     * @param request
     * @param response
     * @param handler      :要执行的handler(目标方法)
     * @param modelAndView :handler返回的ModelAndView对象,如果目标方法没有返回ModelAndView则为null
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2...");
    }

    /**
     * 页面渲染后执行
     *
     * @param request
     * @param response
     * @param handler  :要执行的handler(目标方法)
     * @param ex       :解析JSP页面出现异常时的异常对象
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("afterCompletion2...");
    }
}

添加到SpringMVC中:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <bean class="com.dfbz.interceptor.MyInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <bean class="com.dfbz.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
</mvc:interceptors>

访问:http://localhost:8080/user/login

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/112844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第6章 el-menu刷新保持当前菜单选项与角色页面

1重构&#xff1a;src\components\AdminLayoutComponen.vue(el-menu刷新保持当前菜单选项) <template> <el-container> <!-- 侧边栏 &#xff0c;"<div class"aside">标签可被删除&#xff0c;为了下拉条控件样式保存了该标签"-->…

maven的插件(命令)install介绍

maven的插件&#xff08;命令&#xff09;install介绍背景关于构建时使用的maven命令installmaven其他插件/命令的使用背景 今天在引入SpringCloudAlibaba时&#xff0c;pom.xml中的dependency报错了 到本地仓库去验证 验证无误&#xff0c;找原因 现象&#xff1a; 在maven…

Flink-状态编程(按键分区状态、算子状态、广播状态、持久化与状态后端)

9 状态编程 9.1 概述 9.1.1 状态 所谓的状态&#xff0c;最常见的就是之前到达的数据&#xff0c;或者由之前数据计算出的某个结果 继承富函数类的函数类就可以获取运行时上下文&#xff0c;也就可以自定义状态&#xff0c;例如process中的ProcessFunction&#xff0c;CoPr…

HTML+CSS+svg绘制精美彩色闪灯圣诞树,HTML+CSS+Js实时新年时间倒数倒计时(附源代码)

HTMLCSSsvg绘制精美彩色闪灯圣诞树&#xff0c; HTMLCSSJs实时新年时间倒数倒计时(附源代码) 本篇目录 一、前言 二、主要功能 三、效果展示 四、编码实现步骤 五、资源下载 六、完整源代码&#xff0c;也可下载打包代码&#xff08;我设的是免费&#xff09; 一、前言…

【Vue】三、Vue.js的常用选项

后端程序员的vue学习之路一、选项 / 数据1、data2、computed3、 methods4、computed 与 methods的区别5、watch二、选项 / DOMeltemplate三、选项 / 生命周期钩子1、生命周期钩子有如下这些&#xff1a;2、流程图2、练习代码四、选项 / 资源1、filters2、directives3、componen…

大半夜睡不着,聊一下在小外包公司工作一年后的感想吧

我不知道当年怎么想的&#xff0c;能在一个外包公司一干就是6年&#xff0c;后来终于跳出来了&#xff0c;现在的公司虽然不是什么大厂吧&#xff0c;但至少是个正经的互联网企业&#xff0c;待遇也不错。 其实很多地方的朋友都有提到外包公司的一些弊端&#xff1a; 1.工期短…

自己动手实现一个轮播图组件

1. 轮播图原理 轮播图的原理可以总结为两点&#xff1a; 定位的运用定时器的运用 轮播图的每一张图横向依次排列。在最外层还有一个父级盒子&#xff0c;它的宽度刚好是一张图片的宽度&#xff0c;第一张图没有设置隐藏超出部分&#xff0c;第二张图隐藏了超出部分。 当我们…

河道非法采砂识别系统 yolov5

河道非法采砂识别系统通过yolov5网络架构深度学习技术对河道非法采砂行为进行实时分析检测&#xff0c;如yolov5架构模型发现现场违规采砂&#xff0c;则立即抓拍回传后台。YOLO算法- YOLO算法是一种基于回归的算法&#xff0c;它不是选择图像中有趣的部分&#xff0c;而是预测…

世界杯已开赛,哪些看球设备让你觉得身临其境?

笔者在父亲的影响下&#xff0c;从1994年美国世界杯开始接触足球&#xff0c;因为当时 CCTV5 对拥有着小世界杯之称的意甲转播&#xff0c;成为了一名意大利足球队的忠实拥趸&#xff0c;一直到现在。 四年一次的世界杯也成了我从不错过的足球盛宴。2002年日韩世界杯和2006年德…

Unity使用飞书在线表格做配置表

团队使用飞书进行项目管理&#xff0c;使用在线表格进行配置表的编写&#xff0c;而飞书也提供了在线表格操作的Api&#xff0c;这样我们可以直接在Unity中同步云端表格数据 飞书配置 首先需要进入飞书开发者后台创建应用https://open.feishu.cn/app 创建应用后记录AppId和Ap…

CAJ转pdf在线网址

知网下载论文格式为CAJ&#xff0c;不想下载它的阅读器&#xff0c;网上找了一下转pdf的网站&#xff0c;记录一下&#xff1a; 1.Caj2Pdf在线 https://caj.bookcodes.cn/ 2.speedpdf-CAJ转PDF https://speedpdf.cn/zh-cn/convert/caj-to-pdf?chbaiducp

Android---ViewPager

目录 一、ViewPager 缓存页面与预加载 缓存页面 预加载 预加载带来的问题 解决(性能优化) 二、ViewPager 懒加载机制 ViewPager源码 ViewPager 是怎么展示出来的 Populate FragmentPagerAdapter 三、ViewPager 与 ViewPager2 的差异 一、ViewPager 缓存页面与预加载 …

为什么企业要注重数据安全?六大优势分析

数据加密是将数据从可读格式转换为编码格式。两种最常见的加密方法是对称加密和非对称加密。这些名称是指是否使用相同的密钥进行加密和解密&#xff1a; ●对称加密密钥&#xff1a;这也称为私钥加密。用于编码的密钥与用于解码的密钥相同&#xff0c;使其最适合个人用户和封…

java jar 的修改

java jar 的修改目录概述需求&#xff1a;设计思路实现思路分析1.编译生成class文件2.生产src文件3.单独将对应的java 类编译成class文件4.替换原来的class文件参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full bus…

prettytable辅助打印表格的Python库

这个库的主要作用是&#xff1a;当我们想要结构话的打印一些表格类的数据时会让我们的视觉体验变好 一、安装 一行命令&#xff1a;python -m pip install -U prettytable 搞定 二、使用 1、添加数据 首先来看一个打印的效果 要想实现上边的效果使用下边的代码&#xff1a…

el-Dropdown 两个下拉框之间的动态绑定 实现默认选中值

目录 业务场景 官方链接 实现效果 使用框架 代码展示 template代码 script代码 变量定义 事件定义 onMounted事件 courseClass事件--课程班级绑定 defaultValue事件 optionChange事件 changeClass事件 为什么要给课程的每个选项也绑定click事件&#xff1f;作用是什么…

数字化时代,基于令牌的身份验证是如何工作?

一、背景 数字化转型给用户带来了安全问题&#xff0c;以保护他们的身份免受假冒。据美国诺顿称&#xff0c;平均每年有 80 万个帐户被黑客入侵。需要用于身份验证的高安全性系统和网络安全法规。 传统方法依赖于使用用户名和密码的单级身份验证来授予对 Web 资源的访问权限。…

Superset安装与使用

第1章 Superset入门 1.1 Superset概述 Apache Superset是一个开源的、现代的、轻量级BI分析工具&#xff0c;能够对接多种数据源、拥有丰富的图表展示形式、支持自定义仪表盘&#xff0c;且拥有友好的用户界面&#xff0c;十分易用。 1.2 Superset应用场景 由于Superset能够…

局域网yum仓库搭建

有时候在线的yum源安装特别慢还经常会断,制作自己的一个本地yum源是有必要的。 使用场景,一个服务器集群,只有一台服务器能连接外网,连接外网那台服务器就可以通过reposync把外网源的包全部同步下来放在本地,集群中其他服务器就以这台服务器为包库使用 yum 安装,当然,同…

nginx 后退

nginx 后退目录概述需求&#xff1a;设计思路实现思路分析1.使用nginx的2.配置nginx属性即可参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for chang…