SpringBoot事件驱动开发
应用启动过程生命周期事件感知(9大事件)、应用运行中事件感知(无数种)
- 事件发布:
ApplicationEventPublisherAware
或注入:ApplicationEventMulticaster
- 事件监听:
组件 + @EventListener
场景:
当用户登录后,我们需要为用户增加一个积分、随机获取一张优惠券、增加日志等,传统的开发模式为在用户登录的login()方法后调用积分、优惠券、日志服务。这样在后续的开发中login()方法可能会频繁变动,根据设计模式方法应该对新增开放,修改关闭,所以可以在login()方法中发布登录成功的事件,在积分、优惠券、日志服务增加对事件的监听进行后续处理即可。
编写代码
LoginController.java
在login()方法后发布登录成功事件
package com.atguigu.boot3.core.controller;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.EventPublisher;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @date 2023/10/30 18:57
*/
@RestController
public class LoginController {
@Autowired
EventPublisher eventPublisher;
@GetMapping("/login")
public String login(@RequestParam("username") String username,
@RequestParam("passwd")String passwd){
//业务处理登录
System.out.println("业务处理登录完成....");
//1、创建事件信息
LoginSuccessEvent event = new LoginSuccessEvent(new UserEntity(username, passwd));
//2、发送事件
eventPublisher.publishEvent(event);
//设计模式:对新增开放,对修改关闭
return username+"登录成功";
}
}
LoginSuccessEvent.java
事件定义
通过继承ApplicationEvent类,将source传给父类对象。
package com.atguigu.boot3.core.event;
import com.atguigu.boot3.core.entity.UserEntity;
import org.springframework.context.ApplicationEvent;
/**
* 登录成功事件
* @author 朱俊伟
* @date 2023/10/30 18:56
*/
public class LoginSuccessEvent extends ApplicationEvent {
/**
* @param source 代表是谁登录成了
*/
public LoginSuccessEvent(UserEntity source) {
super(source);
}
}
EventPublisher.java
事件发布器
定义事件发布器,实现
ApplicationEventPublisherAware接口
,用来发布事件
package com.atguigu.boot3.core.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
/**
* @date 2023/10/30 18:58
*/
@Component
public class EventPublisher implements ApplicationEventPublisherAware {
/**
* 底层发送事件用的组件,SpringBoot会通过ApplicationEventPublisherAware接口自动注入给我们
* 事件是广播出去的。所有监听这个事件的监听器都可以收到
*/
ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* 发布事件
* @param event 事件
*/
public void publishEvent(LoginSuccessEvent event) {
applicationEventPublisher.publishEvent(event);
}
}
CouponService.java
优惠券服务
可以通过给方法定义
@EventListener
注解,代表该类监听某种事件
可以给监听器使用@Order(1)
注解定义监听器的顺序,数字越小,越先执行
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 优惠券服务
* @date 2023/10/30 19:06
*/
@Service
@Slf4j
public class CouponService {
@Order(1)
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent){
log.info("CouponService.onEvent....");
UserEntity user = (UserEntity) loginSuccessEvent.getSource();
sendCoupon(user);
}
public void sendCoupon(String username){
System.out.println(username + " 随机得到了一张优惠券");
}
public void sendCoupon(UserEntity user){
sendCoupon(user.getUsername());
}
}
AccountService.java
积分服务
可以实现
ApplicationListener
接口来监听事件
实现onApplicationEvent
方法来进行事件的处理
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 积分服务
* @date 2023/10/30 19:03
*/
@Service
@Slf4j
@Order(2)
public class AccountService implements ApplicationListener<LoginSuccessEvent> {
@Override
public void onApplicationEvent(LoginSuccessEvent event) {
log.info("AccountService.onApplicationEvent.....");
UserEntity user = (UserEntity) event.getSource();
addAccountScore(user);
}
public void addAccountScore(UserEntity user){
System.out.println(user.getUsername() +" 加了1分");
}
}
SysService.java
日志服务
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 日志服务
* @date 2023/10/30 19:09
*/
@Service
@Slf4j
public class SysService {
@EventListener
@Order(3)
public void onEvent(LoginSuccessEvent event){
log.info("SysService.onEvent....");
UserEntity user = (UserEntity) event.getSource();
recordLog(user);
}
public void recordLog(UserEntity user){
System.out.println(user.getUsername() + "登录信息已被记录");
}
}
UserEntity.java
实体类
package com.atguigu.boot3.core.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @date 2023/10/30 18:55
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class UserEntity {
private String username;
private String passwd;
}
调用
http://localhost:8080/login?username=admin&passwd=123
控制台打印结果
业务处理登录完成....
2023-10-30T19:20:11.670+08:00 INFO 11984 --- [nio-8080-exec-5] c.a.boot3.core.service.CouponService : CouponService.onEvent....
admin 随机得到了一张优惠券
2023-10-30T19:20:11.671+08:00 INFO 11984 --- [nio-8080-exec-5] c.a.boot3.core.service.AccountService : AccountService.onApplicationEvent.....
admin 加了1分
2023-10-30T19:20:11.671+08:00 INFO 11984 --- [nio-8080-exec-5] c.atguigu.boot3.core.service.SysService : SysService.onEvent....
admin登录信息已被记录
在业务类中增加方法来实现对事件的监听个人感觉是比较好的方法,可以更好的调节事件处理的顺序以及减少业务类对实现接口的定义。
参考:
https://www.yuque.com/leifengyang/springboot3/lliphvul8b19pqxp#Cq1vD
SpringBoot事件驱动开发的更多相关文章
- springboot区分开发、测试、生产多环境的应用配置(二)
转:https://www.jb51.net/article/139119.htm springboot区分开发.测试.生产多环境的应用配置(二) 这篇文章主要给大家介绍了关于maven profil ...
- SpringBoot Web开发(5) 开发页面国际化+登录拦截
SpringBoot Web开发(5) 开发页面国际化+登录拦截 一.页面国际化 页面国际化目的:根据浏览器语言设置的信息对页面信息进行切换,或者用户点击链接自行对页面语言信息进行切换. **效果演示 ...
- SpringBoot Web开发(4) Thymeleaf模板与freemaker
SpringBoot Web开发(4) Thymeleaf模板与freemaker 一.模板引擎 常用得模板引擎有JSP.Velocity.Freemarker.Thymeleaf SpringBoo ...
- springboot区分开发、测试、生产多环境的应用配置
转:https://blog.csdn.net/daguairen/article/details/79236885 springboot区分开发.测试.生产多环境的应用配置(一) Spring可使用 ...
- 千锋很火的SpringBoot实战开发教程视频
springboot是什么? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员 ...
- springboot 快速开发的定制补充
增强 SpringBoot 快速开发工具 项目地址:https://gitee.com/sanri/web-ui 优点:这是一个 web 通用配置的组件,即插即用,可用于新项目或私活.是对 Sprin ...
- springboot实战开发全套教程,让开发像搭积木一样简单!Github星标已上10W+!
前言 先说一下,这份教程在github上面星标已上10W,下面我会一一给大家举例出来全部内容,原链接后面我会发出来!首先我讲一下接下来我们会讲到的知识和技术,对比讲解了多种同类技术的使用手日区别,大家 ...
- springboot注解开发
可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景.对于每一个注解我都说了具体用法,掌握搞懂,使用 SpringBoot 来开发项 ...
- SpringBoot快速开发REST服务最佳实践
一.为什么选择SpringBoot Spring Boot是由Pivotal团队提供的全新框架,被很多业内资深人士认为是可能改变游戏规则的新项目.早期我们搭建一个SSH或者Spring Web应用,需 ...
- springboot快速开发(简单web)
这是一个springboot基础配置文件介绍的demo.只涉及到 控制层与前端的简单交互,用于验证代码的畅通. spring-boot pom.xml解释 <?xml version=&quo ...
随机推荐
- 使用MTR网络诊断
安装 MTR Ubuntu: apt update apt upgrade apt install mtr-tiny CentOS: yum update yum install mtr 使用 MTR ...
- 8款支持 C# 语言的 AI 辅助编程神器,高效编程利器!
前言 在当今这个AI技术日新月异的时代,一股创新的浪潮正席卷着软件开发领域,其中AI辅助编程工具以其独特的魅力脱颖而出,成为了众多开发者不可或缺的得力助手.这些工具不仅能够显著提升开发效率,优化代码质 ...
- ABB机器人IO板DSQC651维修检查方法
ABB机器人作为工业自动化的重要设备,其稳定性和可靠性对于生产线的持续运行至关重要.然而,在实际使用中,由于各种原因,可能会出现ABB机器人IO板DSQC651故障,影响机器人的正常运行. 一.ABB ...
- TDH - 如何显示Guardian Client角色
注意:本博客适用TDH版本4.3.x 默认该页面的 Guardian Client 是隐藏的,如果需要对 Guardian Client角色进行什么操作的话,需要先将 Guardian Client角 ...
- typora编辑数学公式
最后,需要补充两点: 1.如果要导出为docx,需要安装pandoc https://github.com/jgm/pandoc/releases/tag/3.6.3 2.如果要自己写代码,比如输入\ ...
- python excel 读取:如何读取符合多个条件的记录【出差、外出、调休、年假】
if 语句结合or 实现:读取所有出差.外出.调休.年假的记录 if '出差' in str(c_cell) or '外出' in str(c_cell) or'调休' in str(c_cell) ...
- 从RNN、LSTM到NTM、MANN——神经网络的记忆与推理进化
从RNN.LSTM到NTM.MANN--神经网络的记忆与推理进化 一.前言:为什么要研究记忆? (温馨提示:在阅读本文之前,请确保你已经对深度学习中最基本的概念有一定的了解,例如:激活函数.多层感知机 ...
- 【Loongson】支持AXI总线接口
概述 支持axi接口.但其实没有burst,没有cache,没有tlb,所以仿真起来全是空泡,冲突转发相关功能正确性就测不出来. 从sram改为axi:等待时间从一拍到看信号握手 主要更改/bug处: ...
- FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 🛠️
title: FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 ️ date: 2025/3/12 updated: 2025/3/12 author: cmdragon e ...
- Web前端入门第 11 问:HTML 常用标签有多少?全量标签有多少?
HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 截止发文,MDN 收录的 HTML 全量标签有 126 个,有 18 个标记已弃用. 名词解释:MDN --- ...