重生之 SpringBoot3 入门保姆级学习(18、事件驱动开发解耦合)
- 5、SpringBoot3 核心
- 5.1 原始开发
- 5.2 事件驱动开发
5、SpringBoot3 核心
5.1 原始开发
- LoginController
package com.zhong.bootcenter.controller;
import com.zhong.bootcenter.service.AccountService;
import com.zhong.bootcenter.service.CouponService;
import com.zhong.bootcenter.service.SysService;
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;
/**
* @ClassName : LoginController
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:26
*/
@RestController
public class LoginController {
@Autowired
AccountService accountService;
@Autowired
CouponService couponService;
@Autowired
SysService sysService;
@GetMapping("/login")
public String Login(@RequestParam("username") String username, @RequestParam("password") String password) {
// 业务处理登录
System.out.println("业务处理完成......");
// 1、账户服务: 自动签到加积分
// 2、优惠卷服务: 随机发放优惠卷
// 3、系统服务: 登记用户的信息
accountService.addAccountScore(username);
couponService.sendCoupon(username);
sysService.SysUser(username);
return username;
}
}
- AccountService
package com.zhong.bootcenter.service;
import org.springframework.stereotype.Service;
/**
* @ClassName : AccountService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:30
*/
@Service
public class AccountService {
public void addAccountScore(String username) {
System.out.println(username + " 用户积分+1");
}
}
- CouponService
package com.zhong.bootcenter.service;
import org.springframework.stereotype.Service;
/**
* @ClassName : CouponService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:33
*/
@Service
public class CouponService {
public void sendCoupon(String username) {
System.out.println(username + " 发了一张优惠价");
}
}
- SysService
package com.zhong.bootcenter.service;
import org.springframework.stereotype.Service;
/**
* @ClassName : SysService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:35
*/
@Service
public class SysService {
public void SysUser(String username) {
System.out.println( "记录了 " + username + " 的信息");
}
}
http://localhost:8080/login?username=%22xiaozhong%22&password=%22123456%22
5.2 事件驱动开发
设计模式应该是:对新增开发,对修改关闭。
- LoginController 登录接口
package com.zhong.bootcenter.controller;
import com.zhong.bootcenter.entity.UserEntity;
import com.zhong.bootcenter.event.EventPublisher;
import com.zhong.bootcenter.event.LoginSuccessEvent;
import com.zhong.bootcenter.service.AccountService;
import com.zhong.bootcenter.service.CouponService;
import com.zhong.bootcenter.service.SysService;
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;
/**
* @ClassName : LoginController
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:26
*/
@RestController
public class LoginController {
@Autowired
EventPublisher eventPublisher;
@GetMapping("/login")
public String Login(@RequestParam("username") String username, @RequestParam("password") String password) {
// 业务处理登录
System.out.println("业务处理完成......");
// 1、账户服务: 自动签到加积分
// 2、优惠卷服务: 随机发放优惠卷
// 3、系统服务: 登记用户的信息
// TODO 发送事件
// 1、创建事件信息
LoginSuccessEvent event = new LoginSuccessEvent(new UserEntity(username, password));
// 2、发送事件
eventPublisher.sendEvent(event);
return username;
}
}
- UserEntity 用户类
package com.zhong.bootcenter.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @ClassName : UserEntity
* @Description :
* @Author : zhx
* @Date: 2024-06-12 16:01
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserEntity {
private String username;
private String password;
}
- EventPublisher 事件发送器
package com.zhong.bootcenter.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
/**
* @ClassName : EventPublisher
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:58
*/
@Service
public class EventPublisher implements ApplicationEventPublisherAware {
/**
* 底层发事件使用的组件,SpringBoot会通过 ApplicationEventPublisherAware 接口自动注入给我们
* 事件是广播出去的,所有监听这个事件的监听器都会收到
*/
ApplicationEventPublisher applicationEventPublisher;
/**
* 所有事件都可以发送
* @param event
*/
public void sendEvent(ApplicationEvent event) {
// 调用底层 API 发送事件
applicationEventPublisher.publishEvent(event);
}
/**
* 会被自动调用,把真正发事件的底层组件给我们注入进来
* @param applicationEventPublisher
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
- LoginSuccessEvent 登录成功监听
package com.zhong.bootcenter.event;
import com.zhong.bootcenter.entity.UserEntity;
import org.springframework.context.ApplicationEvent;
/**
* @ClassName : LoginSuccessEvent
* @Description : 登录成功事件,所有事件都推荐继承 ApplicationEvent
* @Author : zhx
* @Date: 2024-06-12 16:00
*/
public class LoginSuccessEvent extends ApplicationEvent {
public LoginSuccessEvent(UserEntity source) {
super(source);
}
}
- AccountService 模拟用户积分 +1
package com.zhong.bootcenter.service;
import com.zhong.bootcenter.entity.UserEntity;
import com.zhong.bootcenter.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
/**
* @ClassName : AccountService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:30
*/
@Service
public class AccountService {
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent) {
System.out.println("===== AccountService =====感知到事件" + loginSuccessEvent);
UserEntity source = (UserEntity) loginSuccessEvent.getSource();
addAccountScore(source.getUsername());
}
public void addAccountScore(String username) {
System.out.println(username + " 用户积分+1");
}
}
- CouponService 模拟给用户发放优惠卷
package com.zhong.bootcenter.service;
import com.zhong.bootcenter.entity.UserEntity;
import com.zhong.bootcenter.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
/**
* @ClassName : CouponService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:33
*/
@Service
public class CouponService {
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent) {
System.out.println("===== CouponService =====感知到事件" + loginSuccessEvent);
UserEntity source = (UserEntity) loginSuccessEvent.getSource();
sendCoupon(source.getUsername());
}
public void sendCoupon(String username) {
System.out.println(username + " 发了一张优惠价");
}
}
- SysService 模拟记录用户登录
package com.zhong.bootcenter.service;
import com.zhong.bootcenter.entity.UserEntity;
import com.zhong.bootcenter.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
/**
* @ClassName : SysService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:35
*/
@Service
public class SysService {
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent) {
System.out.println("===== SysService =====感知到事件" + loginSuccessEvent);
UserEntity source = (UserEntity) loginSuccessEvent.getSource();
SysUser(source.getUsername());
}
public void SysUser(String username) {
System.out.println("记录了 " + username + " 的信息");
}
}
http://localhost:8080/login?username=%22xiaozhong%22&password=%22123456%22
注意:默认触发顺序是按照字母排序,可以通过 @Order(number) 注解调整顺序,number 数字越低优先级越高。如:
package com.zhong.bootcenter.service;
import com.zhong.bootcenter.entity.UserEntity;
import com.zhong.bootcenter.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* @ClassName : SysService
* @Description :
* @Author : zhx
* @Date: 2024-06-12 15:35
*/
@Service
public class SysService {
@Order(1)
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent) {
System.out.println("===== SysService =====感知到事件" + loginSuccessEvent);
UserEntity source = (UserEntity) loginSuccessEvent.getSource();
SysUser(source.getUsername());
}
public void SysUser(String username) {
System.out.println("记录了 " + username + " 的信息");
}
}