spring拦截器 与统一格式
目录
- 前言
- 模拟拦截器
- 拦截器的实现原理
- 什么是动态代理? 什么是静态代理
- 静态代理与动态代理的区别
- 两种常用的动态代理方式
- 基于接口的动态代理
- 基于类的动态代理
- JDK Proxy 与 CGlib的区别
- 其他 统⼀访问前缀添加
- 统⼀异常处理
- 统⼀数据返回格式
前言
之前博客讲述了 , 关于SpringAOP如何实现, 但是在实际开发中, 我们大多数不会遇到SpringAOP, 而是使用Spring拦截器代替了SpringAOP的功能, 因为Spring拦截器 比起AOP来更简单, 更好上手
模拟拦截器
- 创建一个拦截器 - 定义一个类,实现HandlerInterceptor 接口, 并重写preHandle方法 , 在这个类中 ,写业务的判断方法, (注: 这个类只是一个普通类)
package com.example.demo.config;import com.example.demo.common.AppVariable;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class UserInterceptor implements HandlerInterceptor {/**** @param request* @param response* @param handler* @return 返回TRUE的时候, 表示拦截器验证成功, 返回FALSE 表示拦截器验证失败* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {// 业务方法HttpSession session = request.getSession(false); // 默认值是TRUE ,没有会自动创建一个session会话if (session != null && session.getAttribute(AppVariable.SESSION_KEY) != null){// 用户已登录return true;//如果是TRUE就继续执行后续方法}return false;// FALSE 不执行后续方法}
}
- 将拦截器配置到系统的配置文件中, 并配置拦截器的拦截规则
也就是, 定义一个全局类, 加上@Configuration 注解 , 然后实现WebMvcConfigurer接口, 重写addInterceptors 方法, 在方法中定义具体拦截那些资源
注: 一个项目中可以有多个拦截规则
package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration //一定要加一个Configurationpublic class AppConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserInterceptor()) // 这儿也可以使用注解的方式来注入 , 表示具体拦截的类 .addPathPatterns("/**") // 一刀切, 拦截所有的请求.excludePathPatterns("/user/reg") // 配置不拦截的接口.excludePathPatterns("/user/login") // 不拦截的有更多的就写更多的方法;}
}
- 定义一个测试类, 来测试拦截的功能
package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/getuser")public String getUser(){return "do getUser";}@RequestMapping("/reg")public String reg(){return "do reg";}@RequestMapping("/login")public String login(){return "do login";}}
拦截器的实现原理
之前的Spring调用流程

加入拦截器的调用流程

可以看出, 拦截器就是在访问控制层之前, 先将用户的请求处理一遍, 如果正确就给与后序层去调用, 如果不正确就拦截下来,让其实现对应的业务逻辑
拦截器也是通过动态代理的方式来实现的,
什么是动态代理? 什么是静态代理
代理: 就是将我们不愿意做的事情,交给别人去做
我们先来说什么是静态代理: 在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。简单来说静态代理就是在不改变源代码的基础上增加新的功能
比方说: 俩个类都实现了一个接口, 这样类A就可以通过类B 来加强一些自己说不具备的功能, 这种就可以说是静态代理, 因为你是根据代码提前写好去调用其他对象,这些对象在程序运行前就已经加载上了
有了静态代理的概念: 那么动态代理也就很清晰了
我们从上述可以看出静态代理受限于接口的实现。动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的
静态代理与动态代理的区别
静态代理需要自己写代理类并一一实现目标方法,且代理类必须实现与目标对象相同的接口。
动态代理不需要自己实现代理类,它是利用 JDK或CGLib,动态地在内存中构建代理对象(需要我们传入被代理类),并且默认实现所有目标方法。
两种常用的动态代理方式
基于接口的动态代理
是JDK提供的: 必须使用JDK官方的Proxy类创建代理对象,代理的目标对象必须实现接口
基于类的动态代理
是 CGLib提供的: 使用CGLib的Enhancer类创建代理对象
JDK Proxy 与 CGlib的区别
- 出生不同
- 实现不同 , JDK Proxy 要求代理类实现接口才能实现代理 , 而CGLib是实现代理类的子类完成动态代理
- 性能不同, JDK 7 Proxy 性能高于 CGLib , 而JDK 7 之前CGLib性能高于Proxy
其他 统⼀访问前缀添加
所有请求地址添加 api 前缀 , 在实现WebMvcConfigure 接口的类中 ,重写configurePathMatch方法 , 其中第⼆个参数是⼀个表达式,设置为 true 表示启动前缀
@Configuration
public class AppConfig implements WebMvcConfigurer {// 所有的接⼝添加 api 前缀@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix("api", c -> true);}
}
统⼀异常处理
统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件,具体实现代码如下:
⽅法名和返回值可以⾃定义,其中最重要的是@ExceptionHandler(Exception.class) 注解 , 注解中放具体的异常类型, 也可以直接使用Exception来处理所有的异常,
调用流程如下: 定义了Exception异常的前提下, 如果找到对应异常就使用对应异常处理, 找不到就是用Exception异常处理
import java.util.HashMap;
@ControllerAdvice
public class ErrorAdive {@ExceptionHandler(Exception.class)@ResponseBodypublic Object handler(Exception e) {HashMap<String, Object> map = new HashMap<>();map.put("state", 0);map.put("data", null);map.put("msg", e.getMessage());return map;}
}
统⼀数据返回格式
统⼀的数据返回格式可以使⽤ @ControllerAdvice + ResponseBodyAdvice 的⽅式实现,具体实现代
码如下
如果想要使用统一数据的返回格式, 首先在类上加上@ControllerAdvice注解, 然后在类上实现 ResponseBodyAdvice 接口, 并重写俩个方法, support 与beforeBodywrite , 其中support 必须返回TRUE 否则不调用beforeBodywrite 方法, 在beforeBodywrite中写数据返回类型
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.HashMap;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {/*** 内容是否需要重写(通过此⽅法可以选择性部分控制器和⽅法进⾏重写)* 返回 true 表示重写*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}/*** ⽅法返回之前调⽤此⽅法*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType, ServerHttpRequest request,ServerHttpResponse response) {// 构造统⼀返回对象HashMap<String, Object> result = new HashMap<>();result.put("state", 1);result.put("msg", "");result.put("data", body);return result;}
}
相关文章:
spring拦截器 与统一格式
目录 前言模拟拦截器拦截器的实现原理什么是动态代理? 什么是静态代理静态代理与动态代理的区别两种常用的动态代理方式基于接口的动态代理基于类的动态代理 JDK Proxy 与 CGlib的区别 其他 统⼀访问前缀添加统⼀异常处理统⼀数据返回格式 前言 之前博客讲述了 , 关于SpringA…...
leetcode 122. 买卖股票的最佳时机 II
2023.7.29 把整体利润拆分成每天的利润,将股票值想象成一个折线图,将所有上升的值相加即可。 代码: class Solution { public:int maxProfit(vector<int>& prices) {int ans 0;for(int i1; i<prices.size(); i){if(prices[i]-…...
代理模式:控制访问的设计模式
代理模式:控制访问的设计模式 什么是代理模式? 代理模式是一种常见的设计模式,它允许通过代理对象来控制对真实对象的访问。代理模式的主要目的是在不改变原始对象的情况下,提供额外的功能或控制访问。 为什么要使用代理模式&a…...
2020/7/30
Educational Codeforces Round 143 (Rated for Div. 2)\C_Tea_Tasting.cpp //题意:有n种茶,n个人,第i种茶有 a[i]的量,第i个人一次能喝 b[i], 第i个人从第i种茶开始往前喝,求每个人最多能喝多少茶。 //思路ÿ…...
图形编辑器开发:是否要像 Figma 一样上 wasm
大家好,我是前端西瓜哥。 wasm 拿来做 Web 端的图形编辑器貌似是不错的选择。 因为图形处理会有相当多无法利用到 WebGL GPU 加速的 CPU 密集的计算。比如对一条复杂贝塞尔曲线进行三角化,对多个图形进行复杂图形的布尔运算。 图形编辑器性能天花板 F…...
Linux学成之路(基础篇0(二十三)MySQL服务(主从MySQL服务和读写分离——补充)
目录 一、MySQL Replication概述 优点 异步复制(Asynchronous repication) 全同步复制(Fully synchronous replication) 半同步复制(Semisynchronous replication) 三、MySQL支持的复制 四、部署主从…...
spring启动流程 (6完结) springmvc启动流程
SpringMVC的启动入口在SpringServletContainerInitializer类,它是ServletContainerInitializer实现类(Servlet3.0新特性)。在实现方法中使用WebApplicationInitializer创建ApplicationContext、创建注册DispatcherServlet、初始化ApplicationContext等。 SpringMVC…...
设计模式-中介者模式在Java中使用示例-客户信息管理
场景 欲开发客户信息管理窗口界面,界面组件之间存在较为复杂的交互关系:如果删除一个客户, 要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名称也将减少一个; 如果增加一个客户信息,…...
14443-1-doc
介绍 ISO/IEC 14443 是描述 ISO/IEC 7810 中定义的身份证参数以及此类卡在国际交换中的使用的一系列国际标准之一。 ISO/IEC 14443 的这一部分描述了感应卡的物理特性。 ISO/IEC 14443 的这一部分并不排除在卡上纳入其他标准技术,例如资料性附录 A 中引用的技术。非…...
SpringBoot的三层架构以及IOCDI
目录 一、IOC&DI入门 二、三层架构 数据库访问层 业务逻辑层 控制层 一、IOC&DI入门 在软件开发中,IOC(Inversion of Control)和DI(Dependency Injection)是密切相关的概念。 IOC(控制反转&a…...
RabbitMQ部署指南
RabbitMQ部署指南 1.单机部署 我们在Centos7虚拟机中使用Docker来安装。 1.1.下载镜像 方式一:在线拉取 docker pull rabbitmq:3-management方式二:从本地加载 已经提供了镜像包: 上传到虚拟机中后,使用命令加载镜像即可&…...
【Golang】Golang进阶系列教程--Go 语言切片是如何扩容的?
文章目录 前言声明和初始化扩容时机源码分析go1.17go1.18内存对齐 总结 前言 在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。 切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装…...
【数据结构】顺序表(SeqList)(增、删、查、改)详解
一、顺序表的概念和结构 1、顺序表的概念: 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。 2、顺序表的结构: (1)静态顺序表:使…...
[golang gin框架] 42.Gin商城项目-微服务实战之后台Rbac微服务角色增删改查微服务
一.重构后台Rbac用户登录微服务功能 上一节讲解了后台Rbac微服务用户登录功能以及Gorm数据库配置单独抽离,Consul配置单独抽离,这一节讲解后台Rbac微服务角色增删改查微服务功能,Rbac微服务角色增删改查微服务和后台Rbac用户登录微服务是属于…...
项目篇:Echo论坛系统项目
一、登录注册模块 1、注册功能 1.1、注册流程图 1.2、注册代码 /*** 用户注册* param user* return Map<String, Object> 返回错误提示消息,如果返回的 map 为空,则说明注册成功*/public Map<String, Object> register(User user) {Map&l…...
数据可视化(2)
1.柱状图 #柱状图 #bar(x,height,width,*,aligncenter,**kwargs) #height柱子的高度,即y轴上的数据 #width数组的宽度,默认值0.8 #*表示后面的参数为匿名关键字,必须传入参数 #kwargs关键字参数x[1,2,3,4,5] height[random.randint(10,100)f…...
MD-MTSP:斑马优化算法ZOA求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)
一、斑马优化算法ZOA 斑马优化算法(Zebra Optimization Algorithm,ZOA)Eva Trojovsk等人于2022年提出,其模拟斑马的觅食和对捕食者攻击的防御行为。斑马优化算法(Zebra Optimization Algorithm,ZOA&#x…...
【笔试强训选择题】Day32.习题(错题)解析
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:笔试强训选择题 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!! 文章目录 前言 一、Da…...
抖音seo账号矩阵系统源码如何开发布局?
目录 一、 抖音SEO账号矩阵系统源码的开发布局步骤如下: 二。 开发部署源码 三、 开发部署功能设计 1. 短视频AI智能创作 2. 托管式账号管理: 3. 数据分析 4. 智能营销获客 四。 抖音seo源码开发部署交付技术文档包含 五。 开发代码展示: 一、 抖…...
vue项目cdn打包优化
0.用vue ui可以查看项目打包后的情况。 1.定义包的排除 let externals {axios: axios,element-ui: ELEMENT,echarts: echarts,} configureWebpack: {externals: externals }2.配置cdn包资源 // 配置 let cdn {css: [// element-ui csshttps://unpkg.com/element-ui/lib/th…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
