当前位置: 首页 > news >正文

Java:SpringBoot实现ApplicationEvent事件的监听和发布

通过发布订阅模式实现数据的异步处理,比如异步处理邮件发送

新建SpringBoot项目

项目结构

.
├── pom.xml
└── src└── main├── java│   └── com│       └── example│           └── demo│               ├── Application.java│               ├── config│               │   └── TaskPoolConfig.java│               ├── controller│               │   └── IndexController.java│               ├── entity│               │   └── EmailDto.java│               ├── event│               │   └── SendEmailEvent.java│               ├── listener│               │   └── SendEmailListener.java│               └── service│                   ├── SendEmailService.java│                   └── impl│                       └── SendEmailServiceImpl.java└── resources├── application.yml├── static└── templates

pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.7</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

Application.java

package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

TaskPoolConfig.java

package com.example.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;/*** 线程池参数配置**/
@EnableAsync
@Configuration
public class TaskPoolConfig {/*** 自定义线程池**/@Beanpublic Executor taskExecutor() {//返回可用处理器的Java虚拟机的数量 12int i = Runtime.getRuntime().availableProcessors();System.out.println("系统最大线程数  : " + i);ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//核心线程池大小executor.setCorePoolSize(16);//最大线程数executor.setMaxPoolSize(20);//配置队列容量,默认值为Integer.MAX_VALUEexecutor.setQueueCapacity(99999);//活跃时间executor.setKeepAliveSeconds(60);//线程名字前缀executor.setThreadNamePrefix("asyncServiceExecutor -");//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行executor.setAwaitTerminationSeconds(60);//等待所有的任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}
}

EmailDto.java

package com.example.demo.entity;import lombok.Data;@Data
public class EmailDto {private String email;private String subject;private String content;
}

SendEmailEvent.java

package com.example.demo.event;import com.example.demo.entity.EmailDto;
import org.springframework.context.ApplicationEvent;/*** 自定义事件*/
public class SendEmailEvent extends ApplicationEvent {private EmailDto emailDto;public SendEmailEvent(EmailDto emailDto) {super(emailDto);this.emailDto = emailDto;}public EmailDto getEmailDto() {return this.emailDto;}
}

SendEmailListener.java

package com.example.demo.listener;import com.example.demo.entity.EmailDto;
import com.example.demo.event.SendEmailEvent;
import com.example.demo.service.SendEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;/*** 事件监听器*/
@Component
public class SendEmailListener implements ApplicationListener<SendEmailEvent> {@Autowiredprivate SendEmailService sendEmailService;@Async@Overridepublic void onApplicationEvent(SendEmailEvent event) {EmailDto emailDto = event.getEmailDto();this.sendEmailService.sendEmail(emailDto);}
}

SendEmailService.java

package com.example.demo.service;import com.example.demo.entity.EmailDto;public interface SendEmailService {void sendEmail(EmailDto emailDto);
}

SendEmailServiceImpl.java

package com.example.demo.service.impl;import com.example.demo.entity.EmailDto;
import com.example.demo.service.SendEmailService;
import org.springframework.stereotype.Service;@Service
public class SendEmailServiceImpl implements SendEmailService {@Overridepublic void sendEmail(EmailDto emailDto) {try {// 模拟耗时3秒Thread.sleep(3 * 1000);} catch (Exception e) {System.out.println("Email发送异常");}System.out.println("Email发送成功 " + emailDto);}
}

IndexController.java

package com.example.demo.controller;import com.example.demo.entity.EmailDto;
import com.example.demo.event.SendEmailEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IndexController {@Autowiredprivate ApplicationEventPublisher publisher;@GetMapping("/sendEmail")public String sendEmail() {EmailDto emailDto = new EmailDto();emailDto.setEmail("tom@qq.com");emailDto.setSubject("邮件标题");emailDto.setContent("邮件内容");// 发布事件publisher.publishEvent(new SendEmailEvent(emailDto));return "success";}
}

参考

  • Spring事件机制 ApplicationEventPublisher

相关文章:

Java:SpringBoot实现ApplicationEvent事件的监听和发布

通过发布订阅模式实现数据的异步处理&#xff0c;比如异步处理邮件发送 新建SpringBoot项目 项目结构 . ├── pom.xml └── src└── main├── java│ └── com│ └── example│ └── demo│ ├── Application.java│ …...

星戈瑞-Sulfo-Cyanine3 azide?磺酸基-Cy3-N3叠氮基水溶性染料

Sulfo-Cyanine3 azide&#xff1f; 品牌&#xff1a;星戈瑞 CAS号&#xff1a;2055138-89-9 外观&#xff1a; 暗红色晶体 分子量&#xff1a;720.83 分子式&#xff1a;C34H45N6NaO8S2 纯度&#xff1a;95% 储藏条件&#xff1a;-20C 下避光保存 Sulfo-Cyanine3 azide 是一种…...

十大经典排序算法(下)

&#x1f353;个人主页&#xff1a;bit.. &#x1f352;系列专栏&#xff1a;Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.6 快速排序 1. 算法步骤 2. 动图演示 3.代码实现 1.7 堆排序 1. 算法步骤 2. 动图演示 3. 代码实现 1.8 计数排…...

网络协议分析期末复习(四)

目录 0.前言 1.IP层对改善TCP性能支持的机制 2.TCP防止半开放连接的机制 3.TCP协议中强推位&#xff08;P&#xff09;和紧急位&#xff08;U&#xff09;的用法 4.TCP的流量控制和拥塞控制的异同点 异&#xff1a; &#xff08;1&#xff09;两者的特点不同&#xff1a;…...

Matlab对图像和视频的简单处理(图像视频文件读取和输出,转灰度图,取指定帧的图像)

文章目录1.图像文件的读取2.图像效果展示3.将彩色图转换为灰度图4.视频文件的读取5.读取视频中指定帧的图像6.图片文件的报错1.图像文件的读取 语法介绍&#xff1a; A imread(filename) A imread(filename, fmt)参数介绍&#xff1a; filename&#xff1a;要读取的图像文…...

ArrayList源码分析

ArrayList源码分析目标:一、 ArrayList的简介二、ArrayList原理分析2.1 ArrayList的数据结构源码分析2.2 ArrayList默认容量&最大容量2.3 为什么ArrayList查询快&#xff0c;增删慢&#xff1f;2.4 ArrayList初始化容量1、创建ArrayList对象分析&#xff1a;无参数2、创建A…...

SpringBoot IOC、DI、@Autowired、@Resource、作用域

一、初识Spring1.1 Spring是什么Spring是一个轻量级Java开发框架&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的开源框架&#xff0c;为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构&#xff0c;Java开发者可以专…...

链表相关oj题

1.Leetcode203 移除链表元素 解题思路&#xff1a;从头节点开始进行元素删除&#xff0c;每删除一个元素&#xff0c;需要重新链接节点 struct ListNode* removeElements(struct ListNode* head, int val){struct ListNode*dummyheadmalloc(sizeof(struct ListNode));dummyhea…...

【Linux】操作系统(Operator System)

操作系统&#xff08;Operator System &#xff09;一、操作系统的概念二、操作系统的作用三、系统调用和库函数一、操作系统的概念 操作系统是一组控制和管理计算机软硬件资源&#xff0c;为用户提供便捷使用的计算机程序的集合&#xff0c;是配置在计算机硬件系统上的第一层…...

机器学习自学笔记——感知机

感知机预备知识 神经元 ​ 感知机算法最初是由科学家从脑细胞的神经凸起联想而来。如下图&#xff0c;我们拥有三个初始xxx值&#xff0c;x1,x2,x0x_1,x_2,x_0x1​,x2​,x0​。其中x01x_01x0​1为一个初始的常量&#xff0c;专业上称作“偏置”。每个xxx的值都会乘上一个权重…...

C++ Primer第五版_第三章习题答案(21~30)

文章目录练习3.21练习3.22练习3.23练习3.24练习3.25练习3.26练习3.27练习3.28练习3.29练习3.30练习3.21 请使用迭代器重做3.3.3节的第一个练习。 #include <vector> #include <iterator> #include <string> #include <iostream>using std::vector; usi…...

colmap+openmvs进行三维重建流程全记录

window下的colmapopenmvs进行三维重建流程全记录 1.colmap安装与配置 可参考&#xff1a;https://blog.csdn.net/weixin_44153180/article/details/129334018?spm1001.2014.3001.5501 2.openmvs安装与配置 可参考&#xff1a;https://blog.csdn.net/rdw1246010462/article…...

yolov8命令行运行参数详解

序言 整理来自yolov8官方文档常用的一些命令行参数&#xff0c;官方文档YOLOv8 Docs yolov8命令行的统一运行格式为&#xff1a; yolo TASK MODE ARGS其中主要是三部分传参&#xff1a; TASK(可选) 是[detect、segment、classification]中的一个。如果没有显式传递&#xf…...

分布式锁简介

Redis因为单进程、性能高常被用于分布式锁&#xff1b;锁在程序中作用是同步工具&#xff0c;保证共享资源在同一时刻只能被一个线程访问。 Java中经常用的锁synchronized、Lock&#xff0c;但是Java的锁智能保证单机的时候有效&#xff0c;分布式集群环境就无能为力了&#xf…...

【嵌入式Linux学习笔记】Linux驱动开发

Linux系统构建完成后&#xff0c;就可以基于该环境方便地进行开发了&#xff0c;相关的开发流程与MCU类似&#xff0c;但是引入了设备树的概念&#xff0c;编写应用代码要相对复杂一点。但是省去了很多配置工作。 学习视频地址&#xff1a;【正点原子】STM32MP157开发板 字符…...

2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)(H题)(线段树)

又到了万物复苏的季节&#xff0c;家乡的苹果树结果了。像往常一样小龙同学被叫回家摘苹果。 假设需要采摘的一棵树上当前有a颗苹果&#xff0c;那么小龙会采摘⌈a/3⌉颗苹果&#xff0c;其中⌈x⌉表示不小于x的最小整数。 但是&#xff0c;为了可持续发展&#xff0c;若a小于1…...

Linux内核Thermal框架详解十三、Thermal Governor(3)

接前一篇文章Linux内核Thermal框架详解十二、Thermal Governor&#xff08;2&#xff09; 二、具体温控策略 上一篇文章介绍并详细分析了bang_bang governor的源码。本文介绍第2种温控策略&#xff1a;fair_share。 2. fair_share fair_share governor总的策略是频率档位⽐较…...

TikTok品牌出海创世纪(二)

目录 1.推荐算法打造王者品牌 2.品牌聚焦海外Z群体 3.持续扩展应用场景 加速品牌全球化传播 品牌聚焦海外Z群体 “这个地球上&#xff0c;三分之二的人都在用Facebook“&#xff0c;这是对Facebook曾经统治地位最直观的描述。 但如今&#xff0c;这家全球社交媒体巨头的光环正…...

iOS中SDK开发 -- cocoapods库创建

在iOS项目中&#xff0c;经常使用cocoadpods来进行依赖管理以及三方库引入等。引入的三方库一般会有几种形式&#xff1a;一、在Pods目录下可以直接看到源代码的开源库&#xff0c;如AFNetworking&#xff0c;Masonry等常见开源库。二、在Pods目录下拉取的项目文件只能看到对应…...

2023年了,还是没学会内卷....

先做个自我介绍&#xff1a;我&#xff0c;普本&#xff0c;通信工程专业&#xff0c;现在飞猪干软件测试&#xff0c;工作时长两年半。 回望疫情纪元&#xff0c;正好是实习 毕业这三年。要说倒霉也是真倒霉&#xff0c;互联网浪潮第三波尾巴也没抓住&#xff0c;狗屁造富神…...

实用开源工具:3步解决游戏按键冲突的SOCD清理最佳实践指南

实用开源工具&#xff1a;3步解决游戏按键冲突的SOCD清理最佳实践指南 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 你是否曾在激烈的游戏对战中&#xff0c;明明按下了正确的方向键&#xff0c;角色却做出了…...

为什么你的Mac无法写入Windows硬盘?5分钟彻底解决NTFS读写难题

为什么你的Mac无法写入Windows硬盘&#xff1f;5分钟彻底解决NTFS读写难题 【免费下载链接】Free-NTFS-for-Mac Nigate: An open-source NTFS utility for Mac. It supports all Mac models (Intel and Apple Silicon), providing full read-write access, mounting, and manag…...

MongoDB 4.2.7安装后,除了‘show dbs’你还能用命令行做这些事(新手快速上手)

MongoDB 4.2.7安装后命令行实战&#xff1a;从零开始玩转数据库 当你看到show dbs成功显示数据库列表时&#xff0c;说明MongoDB已经准备就绪。但接下来呢&#xff1f;命令行界面就像一片未知海域&#xff0c;而我们将带你从浅滩开始探索。以下是几个能让新手快速获得成就感的实…...

网盘直链下载助手完整指南:一键获取九大网盘真实下载链接

网盘直链下载助手完整指南&#xff1a;一键获取九大网盘真实下载链接 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天…...

RAG 系列(十二):高级分块策略——Parent-Child 与 Contextual Retrieval

分块的两难困境 RAG 系统里有一个经典矛盾: Chunk 太小:向量匹配精准,但返回给 LLM 的内容是片段,缺乏上下文,无法完整回答问题 Chunk 太大:内容完整,但语义太分散,embedding 质量下降,检索命中率降低 这不是调参能解决的问题,而是 Naive 分块的结构性缺陷。 小块适…...

如何永久保存微信聊天记录?WeChatMsg完整指南带你一键备份

如何永久保存微信聊天记录&#xff1f;WeChatMsg完整指南带你一键备份 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

不止于导航:手把手教你用AI Habitat提取并分析3D室内场景的语义分割信息

不止于导航&#xff1a;手把手教你用AI Habitat提取并分析3D室内场景的语义分割信息 在计算机视觉和机器人研究领域&#xff0c;3D场景理解一直是核心挑战之一。传统方法往往依赖于昂贵的硬件设备和复杂的现场数据采集流程&#xff0c;而AI Habitat的出现为研究者提供了一个高…...

Adobe-GenP 3.0:Adobe CC通用补丁工具完整指南与实战教程

Adobe-GenP 3.0&#xff1a;Adobe CC通用补丁工具完整指南与实战教程 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP Adobe-GenP 3.0是一款专为Adobe Creative Clou…...

STM32F103 Flash读写避坑大全:从解锁失败到数据丢失,我踩过的坑你别再踩

STM32F103 Flash读写避坑大全&#xff1a;从解锁失败到数据丢失&#xff0c;我踩过的坑你别再踩 第一次在STM32F103上操作内部Flash时&#xff0c;我以为按照手册步骤就能轻松完成。直到调试灯疯狂闪烁、数据神秘消失、芯片莫名锁死&#xff0c;才意识到这片存储区域远没有想象…...

从根目录到数据区:FAT16与FAT32目录结构差异全解析

1. FAT文件系统基础认知 第一次接触FAT文件系统时&#xff0c;很多人都会被各种专业术语绕晕。其实理解它并不难&#xff0c;我们可以把整个存储设备想象成一本厚厚的记事本。这本记事本最前面有几页固定的"使用说明"&#xff08;系统保留区&#xff09;&#xff0c;…...