如何利用spring自带的事件发布订阅实现各种异步操作

devtools/2024/11/13 0:18:22/

许久不见,小伙伴们!
最近工作确实非常忙碌,今天终于抽空整理了一篇关于如何在实际开发中利用Spring框架自带的事件机制实现异步操作的文章。希望这篇分享能够给大家带来一些启发。

首先,我写这个的原因是因为我实际开发中遇到这么一个开发场景:
我们的一个新项目登录相关的是用的keycloak,这也就说明 我们的用户是存在于keycloak中,我接到的需求是 批量导入用户功能,这也就意味着 我要找到keycloak的批量新增用户接口,但很不幸的时keycloak并没有批量新增用户的接口只有一个新增用户的接口
在这里插入图片描述

那我要批量新增怎么办,只能解析完excel数据UserList然后循环去调这个接口,这个涉及到调用第三方接口还是循环调就考虑异步去调接口了.
废话不多说,直接上代码!!

实现步骤
我先把controller和service代码贴一下 有头有尾看起来比较顺畅
Controller

java">    @PostMapping("/action/import")@ApiOperation(value = "导入用户", notes = "导入用户")public void importFile(@RequestParam MultipartFile file) throws IOException {userService.importFile(file);}

service

java">  @Autowiredprivate CreatorUserPublisher creatorUserPublisher;public void importFile(MultipartFile file) throws IOException {ExcelUtils.importFile(file, UserImportDTO.class, new ImportHandler<>(list -> createAll(list)));}public void createAll(List<UserImportDTO> list) {String eventId = IdUtil.randomUUID();OperationLogUtil.setEventId(eventId);// 判断数据是否有重复dataHandle(list);// 组装用户数据List<UserParam> userParams = new ArrayList<>();for (UserImportDTO userImportDTO : list) {UserParam userParam = new UserParam();userParam.setUsername(userImportDTO.getUsername());userParam.setEmail(userImportDTO.getEmail());userParam.setEnabled(true);List<UserParam.CredentialsDTO> credentials = new ArrayList<>();UserParam.CredentialsDTO credentialsDTO = new UserParam.CredentialsDTO();credentialsDTO.setType("password");credentialsDTO.setValue(userImportDTO.getP6d());credentials.add(credentialsDTO);userParam.setCredentials(credentials);UserParam.AttributesDTO attributesDTO = new UserParam.AttributesDTO();attributesDTO.setProject(userImportDTO.getUsername());userParam.setAttributes(attributesDTO);userParams.add(userParam);}// 异步调用keycloak接口新增用户Map<String, Object> map = new HashMap<>();map.put("userParams", userParams);map.put("eventId", eventId);log.info("发布异步新增keycloak用户任务");creatorUserPublisher.creatorUserList(map);}

以上代码大部分都不重要
下面我来讲一下这个service里面注入了一个
@Autowired
private CreatorUserPublisher creatorUserPublisher;

这个东西的作用就是发布事件
接下来进入正题
1.创建事件类

java">public class CreatorUserEvent extends ApplicationEvent {private static final long serialVersionUID = -1843750195817873742L;private Map<String, Object> map;public CreatorUserEvent(Object source) {super(source);}public CreatorUserEvent(Object source, Map<String, Object> map) {super(source);this.map = map;}public Map<String, Object> getMap() {return map;}
}

2.发布事件
这个就是我们在service里面注入之后发布的创建用户的事件

java">@Service
@Slf4j
public class CreatorUserPublisher implements ApplicationEventPublisherAware {private ApplicationEventPublisher applicationEventPublisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}public void creatorUserList(Map<String, Object> map) {applicationEventPublisher.publishEvent(new CreatorUserEvent(this, map));}
}

3.监听事件
这个就是处理我们之间在service里面发布的创建用户的事件

java">@Service
@Slf4j
public class CreatorUserListener implements ApplicationListener<CreatorUserEvent> {@Autowiredprivate UserService userService;@Overridepublic void onApplicationEvent(CreatorUserEvent creatorUserEvent) {log.info("开始执行异步任务");Map<String, Object> map = creatorUserEvent.getMap();List<UserParam> userParams = (List<UserParam>) map.get("userParams");String eventId = (String) map.get("eventId");for (UserParam userParam : userParams) {if (!userService.addUser(userParam)) {log.error("新增用户失败:{}", userParam.getUsername());throw new SecurityResourceUnavailableException(UserError.ADD_USER_ERROR);}}}
}

到这就完活了 是不是很简单 就三步: 创建事件、发布事件、监听事件

只要service里面的方法执行完之后就会给前端返回响应消息了,后面的事件监听到之后处理的逻辑跟返回前端没关了也不会影响接口超时,如果监听事件处理的逻辑得结果有需要返回前端的话,建议用websocket去处理吧 主动向前端去发送处理结果
希望对你们有帮助。 开心写代码☺


http://www.ppmy.cn/devtools/117109.html

相关文章

[C++进阶[六]]list的相关接口模拟实现

1.前言 本章重点 在list模拟实现的过程中&#xff0c;主要是感受list的迭代器的相关实现&#xff0c;这是本节的重点和难点。 2.list接口的大致框架 list是一个双向循环链表&#xff0c;所以在实现list之前&#xff0c;要先构建一个节点类 template <class T> struct L…

前端框架的对比和选择

在当今的前端开发领域&#xff0c;有多种流行的前端框架可供选择&#xff0c;如 Vue、React 和 Angular。以下是这些框架的对比以及 Vue 的优势&#xff1a; 一、React 特点&#xff1a; 声明式编程&#xff1a;使用 JSX 语法&#xff0c;使得组件的结构和行为更加清晰。虚拟…

通过WinCC在ARMxy边缘计算网关上实现智能运维

随着信息技术与工业生产的深度融合&#xff0c;智能化运维成为提升企业竞争力的关键因素之一。ARMxy系列的ARM嵌入式计算机BL340系列凭借其高性能、高灵活性和广泛的适用性&#xff0c;为实现工业现场的智能运维提供了坚实的硬件基础。 1. 概述 ARMxy BL340系列是专为工业应用…

ProgrammerAI—AI辅助编程学习指南

前言 随着AIGC&#xff08;AI生成内容&#xff09;技术的快速发展&#xff0c;诸如ChatGPT、MidJourney和Claude等大语言模型相继涌现&#xff0c;AI辅助编程工具正逐步改变程序员的工作方式。这些工具不仅可以加速代码编写、调试和优化过程&#xff0c;还能帮助解决复杂的编程…

hexo本地部署-图文教程

hexo本地部署-图文教程 最终效果前置条件安装使用配置主题创建页面标签页分类页友链页404页 个性化设置语言及网站信息设置导航栏,菜单目录头像及背景封面图美化特效 模板页的配置说明页面 Front-matter文章 Front-matter 最终效果 前置条件 你的电脑需要有git,node环境 安装使…

react hooks--useReducer

概述 很多人看到useReducer的第一反应应该是redux的某个替代品&#xff0c;其实并不是 ◼ useReducer仅仅是useState的一种替代方案&#xff1a;  在某些场景下&#xff0c;如果state的处理逻辑比较复杂&#xff0c;我们可以通过useReducer来对其进行拆分&#xff1b; 或…

vue echarts tooltip使用动态模板

先上代码 tooltip: {// 这里是车辆iconshow: true,// trigger: "item",// backgroundColor: "transparent",appendToBody: true,textStyle: {color: "#ffffff" //设置文字颜色},formatter: (params) > {return formatHtml(params.data)},}, …

使用php生成图片

可以用这方法生成图片 水印 字体可以在资源绑定下载&#xff0c;如果字体路径不对&#xff0c;则不会输出文字图片 public function generateImage($text,$id) { header("Cache-Control: no-cache, must-revalidate"); header("Expires: Mon, 26 Jul 1997 05:0…