Apache Commons Chain 与 Spring Boot 整合:构建用户注册处理链
文章目录
- 概述
- 1. 环境准备
- 2. 创建自定义上下文
- 3. 创建命令
- 验证用户输入
- 保存用户数据
- 发送欢迎邮件
- 4. 构建并执行处理链
- 5. 使用处理链
- 6. 运行结果
- 7. 总结
概述
本文档旨在展示如何在 Spring Boot 应用中使用 Apache Commons Chain 来实现一个用户注册的处理链。我们将通过 ChainBase 和 ContextBase 类来组织和管理多个处理步骤,并结合 Spring 的依赖注入和上下文管理功能,以实现一个灵活且可扩展的解决方案。
1. 环境准备
添加依赖
首先,在 pom.xml 中添加必要的 Maven 依赖,确保项目包含了 Apache Commons Chain 和 Spring Boot 的相关库。
<dependencies><!-- Apache Commons Chain --><dependency><groupId>commons-chain</groupId><artifactId>commons-chain</artifactId><version>1.2</version></dependency><!-- Spring Boot Starter Web (或其他你需要的Spring Boot Starter) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
2. 创建自定义上下文
为了在处理链中的每个命令之间传递和共享状态信息,我们需要创建一个继承自 ContextBase 的自定义上下文类。这个类将包含所有与用户注册相关的属性。
import org.apache.commons.chain.Context;
import org.apache.commons.chain.impl.ContextBase;public class RegistrationContext extends ContextBase {private String username;private String password;private boolean isValid;private boolean isSaved;private boolean emailSent;// Getters and Setterspublic String getUsername() {return (String) get("username");}public void setUsername(String username) {put("username", username);}public String getPassword() {return (String) get("password");}public void setPassword(String password) {put("password", password);}public boolean isValid() {return (boolean) get("isValid");}public void setValid(boolean valid) {put("isValid", valid);}public boolean isSaved() {return (boolean) get("isSaved");}public void setSaved(boolean saved) {put("isSaved", saved);}public boolean isEmailSent() {return (boolean) get("emailSent");}public void setEmailSent(boolean emailSent) {put("emailSent", emailSent);}
}
3. 创建命令
接下来,为每个处理步骤创建一个实现 Command 接口的命令类。每个命令负责执行特定的任务,并根据需要更新上下文的状态。
验证用户输入
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;public class ValidateUserCommand implements Command {@Overridepublic boolean execute(Context context) throws Exception {RegistrationContext regContext = (RegistrationContext) context;String username = regContext.getUsername();String password = regContext.getPassword();// 简单的验证逻辑if (username != null && !username.isEmpty() && password.length() >= 6) {regContext.setValid(true);System.out.println("User input is valid.");} else {regContext.setValid(false);System.out.println("Invalid user input.");}// 返回 false 继续执行链中的下一个命令return !regContext.isValid();}
}
保存用户数据
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;public class SaveUserDataCommand implements Command {@Overridepublic boolean execute(Context context) throws Exception {RegistrationContext regContext = (RegistrationContext) context;if (regContext.isValid()) {// 模拟保存用户数据到数据库System.out.println("Saving user data to database...");regContext.setSaved(true);}// 返回 false 继续执行链中的下一个命令return !regContext.isSaved();}
}
发送欢迎邮件
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;public class SendWelcomeEmailCommand implements Command {@Overridepublic boolean execute(Context context) throws Exception {RegistrationContext regContext = (RegistrationContext) context;if (regContext.isSaved()) {// 模拟发送欢迎邮件System.out.println("Sending welcome email to " + regContext.getUsername() + "...");regContext.setEmailSent(true);}// 返回 false 表示链已经完成return !regContext.isEmailSent();}
}
4. 构建并执行处理链
我们将这些命令组合成一个处理链,并在 Spring Boot 应用中配置和执行它。可以使用 @Configuration 类来定义处理链,并通过 @Bean 注解将其注册为 Spring Bean。
import org.apache.commons.chain.Chain;
import org.apache.commons.chain.impl.ChainBase;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RegistrationChainConfig {@Beanpublic Chain registrationChain() {Chain chain = new ChainBase();chain.addCommand(new ValidateUserCommand());chain.addCommand(new SaveUserDataCommand());chain.addCommand(new SendWelcomeEmailCommand());return chain;}
}
5. 使用处理链
最后,我们可以在控制器或服务层中使用这个处理链来处理用户注册请求。这里以控制器为例:
import org.apache.commons.chain.Context;
import org.apache.commons.chain.impl.ContextBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RegistrationController {@Autowiredprivate Chain registrationChain;@PostMapping("/register")public String register(@RequestBody RegistrationRequest request) {// 创建上下文并设置初始数据Context context = new RegistrationContext();((RegistrationContext) context).setUsername(request.getUsername());((RegistrationContext) context).setPassword(request.getPassword());try {// 执行处理链registrationChain.execute(context);// 输出最终状态System.out.println("Registration process completed.");System.out.println("Is valid: " + ((RegistrationContext) context).isValid());System.out.println("Is saved: " + ((RegistrationContext) context).isSaved());System.out.println("Email sent: " + ((RegistrationContext) context).isEmailSent());return "Registration successful!";} catch (Exception e) {e.printStackTrace();return "Registration failed.";}}// 请求体类public static class RegistrationRequest {private String username;private String password;// Getters and Setterspublic String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}
}
6. 运行结果
当你向 /register 端点发送 POST 请求时,例如使用 Postman 或 cURL:
curl -X POST http://localhost:8080/register \
-H "Content-Type: application/json" \
-d '{"username": "john_doe", "password": "securePassword123"}'
你应该会看到如下输出:
User input is valid.
Saving user data to database...
Sending welcome email to john_doe...
Registration process completed.
Is valid: true
Is saved: true
Email sent: true
并且返回响应:
"Registration successful!"
7. 总结
通过本示例,我们展示了如何使用 Apache Commons Chain 和 Spring Boot 来构建一个灵活且可扩展的用户注册处理链。你可以根据实际需求扩展这个示例,例如添加更多的验证规则、数据库交互逻辑或更复杂的邮件发送机制。Apache Commons Chain 提供了一个强大的框架,可以帮助你组织和管理复杂的业务逻辑,而 Spring Boot 则简化了应用程序的开发和部署过程。
相关文章:
Apache Commons Chain 与 Spring Boot 整合:构建用户注册处理链
文章目录 概述1. 环境准备2. 创建自定义上下文3. 创建命令验证用户输入保存用户数据发送欢迎邮件 4. 构建并执行处理链5. 使用处理链6. 运行结果7. 总结 概述 本文档旨在展示如何在 Spring Boot 应用中使用 Apache Commons Chain 来实现一个用户注册的处理链。我们将通过 Chai…...
一、测试工具LoadRunner Professional脚本编写-录制前设置
设置基于URL的脚本 原因:基于HTML的脚本会导致login接口不能正确录制 设置UTF-8 原因:不勾选此项会导致脚本中文变为乱码...
React Native 组件详解之SectionList、StatusBar、Switch、Text 、 TextInput
在本文中,我们将详细介绍 React Native 中的五个常用组件:SectionList、StatusBar、Switch、Text 和 TextInput。每个组件都有其独特的用途和特性,我们将通过示例代码和 API 说明来帮助你更好地理解和使用它们。 SectionList SectionList 是…...
阿里云:aliyun-cli和ali-instance-cli
概念: 这篇文章只是来澄清一下这俩“cli"之间的区别和联系: aliyun cli 和 ali-instance-cli 都是阿里云提供的命令行工具,但它们的功能和使用场景有所不同。 1. aliyun cli 是一个通用的阿里云命令行接口工具,它允许用户…...
Linux 远程连接服务
远程连接服务器简介 什么是远程连接服务器 远程连接服务器通过文字或图形接口方式来远程登录系统,让你在远程终端前登录linux主机以取得可操 作主机接口(shell),而登录后的操作感觉就像是坐在系统前面一样。 远程连接服务器的功…...
Docker 安装和使用
#Docker 安装和使用 文章目录 1. 安装2. 干掉讨厌的 sudo3. 使用镜像源3.1. 使用 upstart 的系统3.2. 使用 systemd 的系统 4. 基本使用4.1. 容器操作4.2. 镜像操作 5. 网络模式说明5.1. bridge 模式5.2. host 模式5.3. container 模式5.4. none 模式 6. 查看 Docker run 启动参…...
web基础和http协议 附:nginx服务的安装
web基础和http协议: https://www.baidu.com/ URL https:// 协议 http:// www.baidu.com/ 域名 web介绍: DNS和域名 DNS解析的方式: 1、运营商 2、/etc/hosts 人工配置的域名和ip地址之间的映射关系 3、/etc/resolv.conf dns服务器的ip地址 bind,内网解析域名和ip地址…...
springboot利用easypoi实现简单导出Excel
vue springboot利用easypoi实现简单导出 前言一、easypoi是什么?二、使用步骤 1.传送门2.前端vue3.后端springboot 3.1编写实体类(我这里是dto,也一样)3.2控制层结尾 前言 今天玩了一下springboot利用easypoi实现excel的导出,以前…...
【前端新手小白】学习Javascript的【开源好项目】推荐
目录 前言 1 项目介绍 1.1 时间日期类 1.2 网页store类 1.3 事件类 1.4 Number类 1.5 String类 1.6 正则验证类 1.7 ajax类 1.8 data数据类 1.9 browser浏览器类 2 学习js-tool-big-box开源项目时有哪些收获 2.1 你可以这样做 2.2 如果你需要使用本项目 2.3 你…...
CentOS7虚拟机 网络适配器 NAT模式和桥接模式区别
一、环境介绍 宿主机:Windows电脑 虚拟机:VMware下的CentOS7 局域网:路由器下的各真实主机组成的网络 内部局域网:宿主机构建的一个内部网路 二、NAT和桥接网络链接模式区别 NAT模式:相当于宿主机构建一个内部局域网&a…...
sql删除冗余数据
工作或面试中经常能遇见一种场景题:删除冗余的数据,以下是举例介绍相应的解决办法。 举例: 表结构: 解法1:子查询 获取相同数据中id更小的数据项,再将id不属于其中的数据删除。-- 注意:mysql中…...
STM32-C语言基础知识
C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程:先清0,再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句,如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…...
【Point-LIO】基于Ubuntu20.04的ROS1平台的Point-LIO部署Mid-360激光雷达
0、前言 Mid360参数 1、代码拉取 2、代码编译运行 文件结构 编译流程: 1、先编译livox_ros_driver2 2、编译整个工程文件 3、运行launch文件(livox_ros_driver2) 成功启动: 3、实物运行 看得出来,在rviz…...
02_Node.js模块化
02_Node.js模块化 知识点自测 以下代码运行的结果是多少? const arr [10, 20, 30] const result arr.map(val > val 1).reduce((sum, val) > sum val, 0) console.log(result) A:60 B:63 <details><summary>答案</…...
网络——HTTP与HTTPS三次握手和四次挥手
HTTP协议本身并不直接处理TCP连接的建立和关闭,这些是由底层的TCP协议来完成的。但是,由于HTTP通常运行在TCP之上,因此理解TCP的三次握手(用于建立连接)和四次挥手(用于关闭连接)对于理解HTTP通…...
ModelScope-Agent(1): 基于开源大语言模型的可定制Agent系统
目录 简介快速入门 简介 github地址 快速入门 看前两篇,调用千问API和天气API # 选用RolePlay 配置agent from modelscope_agent.agents.role_play import RolePlay # NOQArole_template 你扮演一个天气预报助手,你需要查询相应地区的天气&#x…...
开发知识点-uniCloud
开发知识点-uniCloud 服务空间云函数 cloudfunctions云对象importObjectJSON 格式的文档型数据库Collection unicloud数据的指定表集合 DB SchemaJQL 语法参考资料 服务空间 项目关联空间 云函数 cloudfunctions 云对象importObject JSON 格式的文档型数据库 nosql 非关系…...
Redis——主从复制原理
Redis的主从复制原理是其高可用性和分布式读取能力的重要基础。以下是Redis主从复制原理的详细解释: 一、主从复制的基本概念 Redis的主从复制是一种数据复制和备份的方式,它允许一个主节点(Master)将其所有的数据同步到一个或多…...
MATLAB数学建模之画图汇总
MATLAB是一种强大的数学软件,广泛应用于工程计算、控制设计、信号处理等领域。在数学建模中,MATLAB的绘图功能可以帮助我们直观地展示数据和模型结果。 1. 二维数据曲线图 1.1 绘制二维曲线的基本函数 plot函数用于绘制二维平面上的线性坐标曲线图&am…...
Milvus attu - docker 使用 及 版本兼容
文章目录 版本查看attu 和 milvus 的兼容性Docker 加载attu docker 合并到 Milvus文件管理使用 docker compose 挂在 Milvus,登录 attu 出现报错: Error: Failed to connect to Milvus: Error: 1 CANCELLED: Call cancelled 于是检查兼容问题 版本查看 Milvus 版本发布: htt…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
