SpringMVC:拦截器(12)

news/2024/5/20 15:11:57/文章来源:https://blog.csdn.net/qq_43751200/article/details/128996067

拦截器

  • 1. 拦截器概念
  • 2. 拦截器入门案例
    • 2.1 环境准备
    • 2.2 拦截器开发
      • 步骤1: 创建拦截器类
      • 步骤2: 配置拦截器类
      • 步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描
      • 步骤4: 简化SpringMvcSupport的编写
      • 5 测试
  • 3. 拦截器参数解析(了解)
    • 3.1 前置处理方法
    • 3.2 后置处理方法
    • 3.3 完成处理方法
  • 4. 拦截器链配置

1. 拦截器概念

在这里插入图片描述

(1) 浏览器发送一个请求会先到Tomcat的web服务器

(2) Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源

(3) 如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问

(4) 如果是动态资源,就需要交给项目的后台代码进行处理

(5) 在找到具体的方法之前,我们可以去配置过滤器(可以配置多个Filter),按照顺序进行执行

(6) 然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截

(7) 如果满足规则,则进行处理,找到其对应的controller类中的方法进行执行,完成后返回结果

(8) 如果不满足规则,则不进行处理

拦截器要做的事情:

  • 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
  • 作用:
    • 在指定的方法调用前后执行预先设定的代码
    • 阻止原始方法的执行
    • 拦截器就是用来做增强

注意区分过滤器和拦截器

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强

2. 拦截器入门案例

2.1 环境准备

步骤1:创建一个Web的Maven项目
步骤2:在pom.xml中添加所需的jar包

<?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>org.example</groupId><artifactId>springMVC_12_interceptor</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8080</port><path>/</path></configuration></plugin></plugins></build>
</project>

步骤3:编写Controller

package com.itheima.controller;import com.itheima.domain.Book;
import org.springframework.web.bind.annotation.*;/*** @Author Mr.Lu* @Date 2023/2/11 15:16* @ClassName BookController* @Version 1.0*/
@RestController
@RequestMapping("/books")
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ..." + book);return "{'module':'book save'}";}@DeleteMapping("/{id}")public String delete(@PathVariable Integer id){System.out.println("book delete..." + id);return "{'module':'book delete'}";}@PutMappingpublic String update(@RequestBody Book book){System.out.println("book update ... " + book);return "{'module':'book update'}";}@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("book getById ... " + id);return "{'module':'book getById'}";}@GetMappingpublic String getAll(){System.out.println("book getAll...");return "{'module':'book getAll'}";}
}

步骤4:创建模型类Book

package com.itheima.domain;/*** @Author Mr.Lu* @Date 2023/2/11 15:12* @ClassName Book* @Version 1.0*/
public class Book {private String name;private double price;public Book() {}public Book(String name, double proce) {this.name = name;this.price = proce;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getProce() {return price;}public void setProce(double proce) {this.price = proce;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", proce=" + price +'}';}
}

步骤5:创建对应的配置类

@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}
package com.itheima.config;import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;import javax.servlet.Filter;public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {/*** 加载springmvc配置类** @return*/@Overrideprotected WebApplicationContext createServletApplicationContext() {AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();ctx.register(SpringMvcConfig.class);return ctx;}/*** 设置由springmvc控制器处理的请求映射路径** @return*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}/*** 加载spring配置类** @return*/@Overrideprotected WebApplicationContext createRootApplicationContext() {
//        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
//        ctx.register(SpringConfig.class);
//        return ctx;return null;}// 乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

2.2 拦截器开发

步骤1: 创建拦截器类

在com.itheima目录下面建一个interceptor包,在interceptor包下面建一个实现HandlerIntercepror接口的类,并重写里面的额三个方法。

注意: 拦截器中的preHandler方法,如果返回true,则代表放行,会执行原始Controller类中要请求的方法,如果返回false,则代表拦截,后面的就不会再执行了。

在这里插入图片描述

当有拦截器后,请求会先进入preHandle方法,

  1. 如果方法返回true,则放行继续执行后面的handle[controller的方法]和后面的方法

  2. 如果返回false,则直接跳过后面方法的执行。

package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor 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: 配置拦截器类

在config目录下创建一个类来配置拦截器类

package com.itheima.config;import com.itheima.interceptor.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;/*** @Author Mr.Lu* @Date 2023/2/12 15:13* @ClassName SpringMvcSupport* @Version 1.0*/
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowired(required = false)private ProjectInterceptor projectInterceptor;//    @Override
//    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
//    }@Overrideprotected void addInterceptors(InterceptorRegistry registry) {// 配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*"); // 为可变参数,可以写几种路径}
}

步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描

@Configuration
@ComponentScan({"com.itheima.controller", "com.itheima.interceptor", "com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {
}

步骤4: 简化SpringMvcSupport的编写

让SpringMvcConfig类实现WebMvcConfigurer接口。

@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
// 实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate ProjectInterceptor projectInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置多拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}
}

5 测试

访问http://localhost:8080/books

在这里插入图片描述

在这里插入图片描述

访问http://localhost:8080/books/666
在这里插入图片描述

在这里插入图片描述

3. 拦截器参数解析(了解)

3.1 前置处理方法

原始方法之前运行preHandle

public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {System.out.println("preHandle");return true;
}
  • request:请求对象
  • response:响应对象
  • handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装

3.2 后置处理方法

原始方法运行后运行,如果原始方法被拦截(前置方法返回false),则不执行

public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {System.out.println("postHandle");
}

modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整

3.3 完成处理方法

拦截器最后执行的方法,无论原始方法是否执行(只要前置方法返回true,那么完成处理方法就一定执行

public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {System.out.println("afterCompletion");
}

4. 拦截器链配置

步骤1:创建拦截器类:实现接口,并重写接口中的方法

拦截器2: ProjectInterceptor2

package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @Author Mr.Lu* @Date 2023/2/12 15:09* @ClassName ProjectInterceptor* @Version 1.0*/// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor2 implements HandlerInterceptor {@Override// 原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...222");return true;}@Override// 原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...222");}@Override// 原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...222");}
}

拦截器3:ProjectInterceptor3

package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @Author Mr.Lu* @Date 2023/2/12 15:09* @ClassName ProjectInterceptor* @Version 1.0*/// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor3 implements HandlerInterceptor {@Override// 原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...333");return true;}@Override// 原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...333");}@Override// 原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...333");}
}

步骤2:配置拦截器类

package com.itheima.config;import com.itheima.interceptor.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;/*** @Author Mr.Lu* @Date 2023/2/12 15:13* @ClassName SpringMvcSupport* @Version 1.0*/
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowired(required = false)private ProjectInterceptor projectInterceptor;@Autowired(required = false)private ProjectInterceptor2 projectInterceptor2;@Autowired(required = false)private ProjectInterceptor3 projectInterceptor3;//    @Override
//    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
//    }@Overrideprotected void addInterceptors(InterceptorRegistry registry) {// 配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");registry.addInterceptor(projectInterceptor2).addPathPatterns("/books", "/books/*");registry.addInterceptor(projectInterceptor3).addPathPatterns("/books", "/books/*");}
}

步骤3:运行程序,观察顺序

在这里插入图片描述

拦截器执行的顺序是和配置顺序有关,先进后出。

  • 当配置多个拦截器时,形成拦截器链
  • 拦截器链的运行顺序参照拦截器添加顺序为准
  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作

注:

  1. 当ProjectInterceptor,ProjectInterceptor2,ProjectInterceptor3中的preHandle方法都返回true时,拦截器链执行顺序为:pre1, pre2, pre3, Controller, post3, post2, post1, after3, after2, after1.

  2. 当ProjectInterceptor,ProjectInterceptor2中的preHandle方法返回true,ProjectInterceptor3中的preHandle方法返回false时,拦截器链执行顺序为:pre1, pre2, pre3, after2, after1.

  3. 当ProjectInterceptor中的preHandle方法返回true,ProjectInterceptor2中的preHandle方法返回false时,拦截器链执行顺序为:pre1, pre2, after1.

  4. 当ProjectInterceptor中的preHandle方法返回false时,拦截器链执行顺序为:pre1
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Call for papers】SIGCOMM-2023(CCF-A/计算机网络/2023年2月15日截稿)

ACM SIGCOMM is the flagship annual conference of the ACM Special Interest Group on Data Communication (SIGCOMM). ACM SIGCOMM 2023, the 37th edition of the conference series, will be held in New York City, US, September 10 - 14, 2023. 文章目录1.会议信息2.时…

Redis集群搭建(主从、哨兵、分片)

1.单机安装Redis 首先需要安装Redis所需要的依赖&#xff1a; yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录&#xff1a; 例如&#xff0c;我放到了/tmp目录&#xff1a; 解压缩&#xff1a; tar -xzf redis-6.2.4.tar.gz解压后&#xff1…

OpenPPL PPQ量化(5):执行引擎 源码剖析

目录 PPQ Graph Executor(PPQ 执行引擎) PPQ Backend Functions(PPQ 算子库) PPQ Executor(PPQ 执行引擎) Quantize Delegate (量化代理函数) Usage (用法示例) Hook (执行钩子函数) 前面四篇博客其实就讲了下面两行代码&#xff1a; ppq_ir load_onnx_graph(onnx_impor…

FlinkCEP - Flink的复杂事件处理

版本说明 本文中以Flink 1.16.1 版本讲解说明 Note:Flink1.16.1版本相较于之前版本增强的within函数&#xff0c; 支持模式序列中相邻事件间的超时定义&#xff0c;以前版本只支持模式序列中第一个事件到最后一个事件之间的最大时间间隔。 快速开始 基于Kafka connecter 流…

《计算机组成与设计》01. 计算机抽象及相关技术

文章目录计算机体系结构中的 8 个伟大思想面向摩尔定律的设计使用抽象简化设计加速经常性事件通过并行提高性能通过流水线提高性能存储层次通过冗余提高可靠性性能性能的度量时钟周期数和时钟周期长度与CPU时间的公式指令性能公式经典的 CPU 性能公式CPI 计算公式程序执行时间计…

【前端】Vue项目:旅游App-(23)detail:房东介绍、热门评论、预定须知组件

文章目录目标过程与代码房东介绍landlord热门评论HotComment预定须知Book效果总代码修改或添加的文件detail.vuedetail-book.vuedetail-hotComment.vuedetail-landlord.vue参考本项目博客总结&#xff1a;【前端】Vue项目&#xff1a;旅游App-博客总结 目标 根据detail页面获…

Sa-Token实现分布式登录鉴权(Redis集成 前后端分离)

文章目录1. Sa-Token 介绍2. 登录认证2.1 登录与注销2.2 会话查询2.3 Token 查询3. 权限认证3.1 获取当前账号权限码集合3.2 权限校验3.3 角色校验4. 前后台分离&#xff08;无Cookie模式&#xff09;5. Sa-Token 集成 Redis6. SpringBoot 集成 Sa-Token6.1 创建项目6.2 添加依…

ChatGPT不是聊天机器人,是任何人值得重视的竞争对手。

ChatGPT使用了一种聊天界面来和用户互动&#xff0c;用户的理解成本降低&#xff0c;通过输入文字&#xff0c;来得到各种反馈。有预见性的创造者们&#xff0c;已经挖掘ChatGPT所展示出来的各种能力应该如何更好地融入我们的日常生活中。比如&#xff0c;生成菜谱、音乐播放列…

嵌入式开发----示波器入门

示波器入门前言一、示波器介绍关键指标工作原理二、功能按钮介绍三、一键入门四、 典型应用场景校准捕捉测试总线通讯总结前言 对于嵌入式工程师来说&#xff0c;示波器的使用极为重要&#xff0c;他就像是“电子工程师的眼睛”&#xff0c;把被测信号的实际波形显示在屏幕上&…

越界访问数组

越界访问是指访问&#xff08;操作修改&#xff09;了不属于自己的空间 我们以如下代码为例&#xff1a;此代码在vs中进行 #include <stdio.h> int main() {int i 0;int arr[] {1,2,3,4,5,6,7,8,9,10};for(i0; i<12; i){arr[i] 0;printf("hello\n");}r…

STM32单片机蓝牙APP可烘干升降晾衣架带照明灯

实践制作DIY- GC0123-蓝牙APP可烘干升降晾衣架 一、功能说明&#xff1a; 基于STM32单片机设计-蓝牙APP可烘干升降晾衣架 功能介绍&#xff1a; 硬件组成&#xff1a; STM32F103C系列最小系统单片机1个uln2003步进电机&#xff08;模拟升降&#xff09;1个uln2003步进电机&a…

python+django大学生成绩综合考评系统pycharm项目

开发语言&#xff1a;Python 框架&#xff1a;django Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;PyCharm 通常 一个Django model 对应一张数据表&#xff0c;model是以类的形式表现的 实现了ORM 对象…

第3章-进程同步、互斥与信号量(4)

进程同步、互斥与信号量 0 引言 操作系统的并发进程有些是独立的&#xff0c;有些需要相互协作。独立的进程在系统中执行时不受其他进程的影响&#xff0c;而另一些进程需要与其他进程共享数据&#xff0c;来完成共同的任务&#xff0c;这些进程之间具有协作关系。但我们要保…

C语言(通用函数qsort())

qsort()用于数组排序 void sqort(void *base,size_t nmemb,size_t size,int (*compar)(const void *,const void *)); 第一个参数&#xff1a;指向数组的指针 ANSI C允许把指向任何数据类型的指针强制转换成指向void的指针&#xff0c;因此&#xff0c;第一个参数可以引用任何…

【C++初阶】十二、STL---反向迭代器的实现

目录 一、反向迭代器 二、反向迭代器的实现 一、反向迭代器 之前的模拟实现vector、list 的时候&#xff0c;这些都是实现了正向迭代器&#xff0c;反向迭代器都没有实现&#xff0c;这里就要实现反向迭代器 反向迭代器也是适配器&#xff08;配接器&#xff09;的一种&#…

Unity SRP自定义渲染管线学习2.2: 合批(Batching) SRP Batcher

接下来我们要来学习下自定义渲染管线中的合批&#xff0c;这一节主要学习SRP Batcher 每一次的Draw Call都需要CPU和GPU之间的通信&#xff0c;如果有大量的数据需要从CPU发送到GPU中&#xff0c;那GPU就可能因为等待数据而浪费时间&#xff0c;而CPU会因为忙于发送数据导致无…

[]复习]cityengine2019/2022导入shp数据生成福田区建筑群

时间是一把杀猪刀 和人工智能比起来我太弱了.很无助.无法给自己升级系统. cityengine2019目前载入那种地区线上数据是行不通了,2022可以整一个邮箱试用一个月.https://www.esri.com/zh-cn/arcgis/products/arcgis-cityengine/trial/professionals 我整了一个万能无线邮箱,任意x…

《Spring源码深度分析》第8章 数据库连接JDBC

目录标题前言一、数据库连接方式1.JDBC连接数据库2.Spring Jdbc连接数据库(JdbcTemplate)二、JdbcTemplate源码分析1.update/save功能的实现源码分析入口(关键)基础方法execute1.获取数据库连接池2.应用用户设定的输入参数3. 调用回调函数处理4. 资源释放Update中的回调函数2.q…

mycat安装

查看是否安装jdk java -versionjdk安装方法 mycat下载&#xff1a; Mycat安装包1.6.7.3版本 创建新文件夹 mkdir test_mycat上传jar后移动到对应位置 mv Mycat-server-1.6.7.3-release-20210913163959-linux.tar.gz ./test_mycat/解压 tar zxvf Mycat-server-1.6.7.3-rele…

select 与 where、group by、order by、limit 子句执行优先级比较

当 select 和 其他三种语句的一者或者多者同时出现时&#xff0c;他们之间是存在执行先后顺序的。 他们的优先级顺序是&#xff1a;where > group by > select > order by > limit 目录 1、select 与 where 2、group by 与 where 、select 2、select 与 order…