工作实战之拦截器模式
目录
前言
一、结构中包含的角色
二、拦截器使用
1.拦截器角色
a.自定义拦截器UserValidateInterceptor,UserUpdateInterceptor,UserEditNameInterceptor
b.拦截器配置者UserInterceptorChainConfigure,任意组装拦截器顺序
c.拦截器管理者UserInterceptorChainManager
2.运行结果展示
a.使用代码
三、拦截器调用解说
1.项目启动,初始化bean
2.方法执行
四、代码下载
总结
前言
拦截过滤器模式,简称拦截器模式,是责任链模式的一种衍生模式。用于对业务程序做一些预处理/后处理
一、结构中包含的角色
- Interceptor(抽象处理者)
- InterceptorChain(责任链)
- InterceptorChainBuilder(责任链建造者)
- AbstractInterceptorChainManager(链条管理者)
- InterceptorChainConfigure(链条配置者)
二、拦截器使用
1.拦截器角色

a.自定义拦截器UserValidateInterceptor,UserUpdateInterceptor,UserEditNameInterceptor
/*** 校验用户* @author liangxi.zeng*/
@Component
public class UserValidateInterceptor implements Interceptor<User> {/*** 拦截方法** @param user*/@Overridepublic void interceptor(User user) {if(user.getAge() != 10) {throw new CommonException("年龄不对");}System.out.println("校验用户"+user);}
}
b.拦截器配置者UserInterceptorChainConfigure,任意组装拦截器顺序
@Component
public class UserInterceptorChainConfigureimplements InterceptorChainConfigure<User,InterceptorChainBuilder<User>> {/*** 拦截器链配置** @param interceptorChainBuilder 拦截器链构造器*/@Overridepublic void configure(InterceptorChainBuilder<User> interceptorChainBuilder) {interceptorChainBuilder.pre().addInterceptor(UserValidateInterceptor.class).post().addInterceptor(UserUpdateInterceptor.class).addInterceptor(UserEditNameInterceptor.class);}
}
c.拦截器管理者UserInterceptorChainManager
/*** @author liangxi.zeng* 拦截器链管理类*/
@Component
public class UserInterceptorChainManager
extends AbstractInterceptorChainManager<User> {public UserInterceptorChainManager(List<Interceptor<User>> interceptorList,List<InterceptorChainConfigure<User, InterceptorChainBuilder<User>>> configureList) {super(interceptorList, configureList);}
}
2.运行结果展示
a.使用代码
/*** @author liangxi.zeng*/
@RestController
@RequestMapping("/demo")
public class DemoController {@Autowiredprivate UserInterceptorChainManager userInterceptorChainManager;@Autowiredprivate UserService userService;@RequestMapping("/user")public String user() {User user = new User();user.setId("111");user.setName("liangxi");user.setAge(10);userInterceptorChainManager.doInterceptor(user,(u) -> {// 内部创建用户userService.save(user);});return "success";}}

三、拦截器调用解说
1.项目启动,初始化bean
a.初始化责任链管理者UserInterceptorChainManager,调用父类AbstractInterceptorChainManager方法initInterceptorChain,通过责任链建造者初始化责任链
public AbstractInterceptorChainManager(List<Interceptor<T>> interceptorList,List<InterceptorChainConfigure<T, InterceptorChainBuilder<T>>> configureList) {interceptorChain = initInterceptorChain(interceptorList, configureList);LOGGER.info("Register {} InterceptorChain, names are [{}]",interceptorList);}private InterceptorChain<T> initInterceptorChain(List<Interceptor<T>> interceptorList,List<InterceptorChainConfigure<T, InterceptorChainBuilder<T>>> configureList) {if (CollectionUtils.isEmpty(interceptorList)) {throw new IllegalArgumentException("Interceptors is empty.");}if (CollectionUtils.isEmpty(configureList)) {throw new IllegalArgumentException("Interceptor configurers is empty.");}InterceptorChainBuilder<T> builder = new InterceptorChainBuilder<>(interceptorList);configureList.sort(AnnotationAwareOrderComparator.INSTANCE);configureList.forEach(configurer -> {configurer.configure(builder);});return builder.performBuild();}
b.责任链建造者,完成对业务方法前后逻辑的织入
public InterceptorChain performBuild() {List<Interceptor<T>> preInterceptors = filterInterceptor(preInterceptorList);List<Interceptor<T>> postInterceptors = filterInterceptor(postInterceptorList);if (preInterceptors.isEmpty() && postInterceptors.isEmpty()) {throw new IllegalStateException("Registered Pre-Interceptors and Post-Interceptors is empty.");}Consumer<T> preConsumer = (T t) -> {};Consumer<T> postConsumer = (T t) -> {};if (!preInterceptors.isEmpty()) {preConsumer = (T obj) -> {for (Interceptor<T> item : preInterceptors) {item.interceptor(obj);}};}if (!postInterceptors.isEmpty()) {postConsumer = (T obj) -> {for (Interceptor<T> item : postInterceptors) {item.interceptor(obj);}};}return new InterceptorChain(preConsumer,postConsumer);}
2.方法执行
a.从userInterceptorChainManager.doInterceptor 到 interceptorChain.doExecute(target, operation);下面代码,完成代码逻辑
/*** 拦截器调用入口,将核心操作封装成 Consumer 对象传入。** @param target The target to handle.* @param operation The core operation to intercept.*/public final void doExecute(T target, Operation<T> operation) {preConsumer.accept(target);if (operation != null) {operation.execute(target);}postConsumer.accept(target);}
四、代码下载
设计模式可运行代码
https://gitee.com/zenglx/design-pattern.git
总结
前后端请求,可以用现成的filter和spring的Interceptor解决,业务自己的拦截器链模式,可以解决繁琐业务重复代码的问题
相关文章:
工作实战之拦截器模式
目录 前言 一、结构中包含的角色 二、拦截器使用 1.拦截器角色 a.自定义拦截器UserValidateInterceptor,UserUpdateInterceptor,UserEditNameInterceptor b.拦截器配置者UserInterceptorChainConfigure,任意组装拦截器顺序 c.拦截器管理者…...
某美颜app sig参数分析
之前转载过该app的文章,今天翻版重新整理下,版本号:576O5Zu56eA56eAYXBwIHY5MDgw (base64 解码)。 上来先抓个包: jadx搜索关键词 "sigTime",然后定位到这里 看这行代码 cVar.addForm(INoCaptchaComponent.sig, genera…...
Linux - Linux系统优化思路
文章目录影响Linux性能的因素CPU内存磁盘I/O性能网络宽带操作系统相关资源系统安装优化内核参数优化文件系统优化应用程序软件资源系统性能分析工具vmstat命令iostat命令sar命令系统性能分析标准小结影响Linux性能的因素 CPU CPU是操作系统稳定运行的根本,CPU的速…...
2.Elasticsearch入门
2.Elasticsearch入门[toc]1.Elasticsearch简介Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。 能够达到实时搜索,稳定,可靠,快速,安装使用方便。客户端支持Java、.NET(C#)、PHP、Pyth…...
RK3399平台开发系列讲解(应用开发篇)断言的使用
🚀返回专栏总目录 文章目录 一、什么是断言二、静态断言三、运行时断言沉淀、分享、成长,让自己和他人都能有所收获!😄 📢断言为我们提供了一种可以静态或动态地检查程序在目标平台上整体状态的能力,与它相关的接口由头文件 assert.h 提供。 一、什么是断言 在编程中…...
云原生系列之使用prometheus监控nginx
前言 大家好,又见面了,我是沐风晓月,本文主要讲解云原生系列之使用prometheus监控nginx 文章收录到 csdn 我是沐风晓月的博客【prometheus监控系列】专栏,此专栏是沐风晓月对云原生prometheus的的总结,希望能够加深自…...
第六届省赛——8移动距离(总结规律)
题目:X星球居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为1,2,3...当排满一行时,从下一行相邻的楼往反方向排号。比如:当小区排号宽度为6时,开始情形如下:1 2 3 4 5 612 11 10 9 8 713 14 1…...
C++vector 简单实现
一。概述 vector是我们经常用的一个容器,其本质是一个线性数组。通过对动态内存的管理,增删改查数据,达到方便使用的目的。 作为一个线性表,控制元素个数,容量,开始位置的指针分别是: start …...
通用缓存存储设计实践
目录介绍 01.整体概述说明 1.1 项目背景介绍1.2 遇到问题记录1.3 基础概念介绍1.4 设计目标1.5 产生收益分析 02.市面存储方案 2.1 缓存存储有哪些2.2 缓存策略有哪些2.3 常见存储方案2.4 市面存储方案说明2.5 存储方案的不足 03.存储方案原理 3.1 Sp存储原理分析3.2 MMKV存储…...
sheng的学习笔记Eureka Ribbon
Eureka-注册中心Eureka简介官方网址:https://spring.io/projects/spring-cloud-netflixEureka介绍Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现(请对比Zookeeper)。Zooleeper nacos.Eureka 采用了 C-S 的设计架构。Eureka Server 作为服…...
零代码工具我推荐Oracle APEX
云原生时代零代码工具我推荐Oracle APEX 国内的低码开发平台我也看了很多,感觉还是不太适合我这个被WEB抛弃的老炮。自从看了Oracle APEX就不打算看其它的了。太强大了,WEB服务器都省了,直接数据库到WEB页面。功能很强大,震撼到我…...
InstructGPT方法简读
InstructGPT方法简读 引言 仅仅通过增大模型规模和数据规模来训练更大的模型并不能使得大模型更好地理解用户意图。由于数据的噪声极大,并且现在的大多数大型语言模型均为基于深度学习的“黑箱模型”,几乎不具有可解释性和可控性,因此&…...
SpringCloud-5_模块集群化
避免一台Server挂掉,影响整个服务,搭建server集群创建e-commerce-eureka-server-9002微服务模块【作为注册中心】创建步骤参考e-commerce-eureka-server-9001修改pom.xml,加入依赖同9001创建resources/application.yml9002的ymlserver: # 修改端口号por…...
AQS底层源码深度剖析-BlockingQueue
目录 AQS底层源码深度剖析-BlockingQueue BlockingQueue定义 队列类型 队列数据结构 ArrayBlockingQueue LinkedBlockingQueue DelayQueue BlockingQueue API 添加元素 检索(取出)元素 BlockingQueue应用队列总览图 AQS底层源码深度剖析-BlockingQueue【重点中的重…...
Kotlin协程:Flow的异常处理
示例代码如下:launch(Dispatchers.Main) {// 第一部分flow {emit(1)throw NullPointerException("e")}.catch {Log.d("liduo", "onCreate1: $it")}.collect {Log.d("liudo", "onCreate2: $it")}// 第二部分flow …...
qt下ffmpeg录制mp4经验分享,支持音视频(h264、h265,AAC,G711 aLaw, G711muLaw)
前言 MP4,是最常见的国际通用格式,在常见的播放软件中都可以使用和播放,磁盘空间占地小,画质一般清晰,它本身是支持h264、AAC的编码格式,对于其他编码的话,需要进行额外处理。本文提供了ffmpeg录…...
C#读取Excel解析入门-1仅围绕三个主要的为阵地,进行重点解析,就是最理性的应对上法所在
业务中也是同样的功能点实现。只是多扩展了很多代码,构成了项目的其他部分,枝干所在。但是有用的枝干,仅仅不超过三个主要的!所以您仅仅围绕三个主要的为阵地,进行重点解析,就是最理性的应对上法所在了 str…...
一起Talk Android吧(第五百一十八回:在Android中使用MQTT通信五)
文章目录 知识回顾问题描述解决过程经验分享各位看官们大家好,这一回中咱们说的例子是" 在Android中使用MQTT通信五",本章回内容与前后章节内容无关联。闲话休提,言归正转,让我们一起Talk Android吧! 知识回顾 我们在前面章回中介绍了如何使用MQTT通信,包含它…...
100种思维模型之混沌与秩序思维模型-027
人类崇尚秩序与连续性,我们习惯于我们的日常世界,它以线性方式运作,没有不连续或突跳。 为此,我们学会了期望各种过程以连续方式运行,我们的内心为了让我们更有安全感,把很多事物的结果归于秩序,…...
Java开发 - Redis初体验
前言 es我们已经在前文中有所了解,和es有相似功能的是Redis,他们都不是纯粹的数据库。两者使用场景也是存在一定的差异的,本文目的并不重点说明他们之间的差异,但会简要说明,重点还是在对Redis的了解和学习上。学完本…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
