Springboot之监听器
Springboot之事件监听器
事件监听的几种方式
1 实现接口
场景:用户注册成功后,给用户赠送100元优惠券
1.1 创建事件
实现ApplicationEvent接口
package com.per.listener.e1;
import com.per.domain.UserDto;
import org.springframework.context.ApplicationEvent;
/**
* @Title DemoEvent1
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public class UserEvent extends ApplicationEvent {
/**
* 事件源
*/
private UserDto userDto;
public UserEvent(UserDto userDto) {
super(userDto);
this.userDto = userDto;
}
/**
* 获取事件中的用户信息
*
* @return
*/
public UserDto getUserDto() {
return userDto;
}
}
1.2 创建事件监听器
实现ApplicationListener接口,重写onApplicationEvent方法
package com.per.listener.e1;
import com.per.domain.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @Title UserListener
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Slf4j
@Component
public class UserListener implements ApplicationListener<UserEvent> {
@Override
public void onApplicationEvent(UserEvent event) {
log.info("UserListener#onApplicationEvent 事件监听 开始执行...");
UserDto userDto = event.getUserDto();
// 给用户发优惠券
log.info("给用户{}发送100元优惠卷", userDto.getName());
}
}
1.3 发布事件
引入ApplicationContext,调用publishEvent方法发布事件
package com.per.service.impl;
import com.per.domain.UserDto;
import com.per.listener.e1.UserEvent;
import com.per.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
/**
* @Title UserServiceImpl
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
private ApplicationContext applicationContext;
@Override
public String userRegister(UserDto userDto) {
log.info("用户{}注册成功,注册信息: {}", userDto.getName(), userDto.toString());
// 发送优惠券
UserEvent userEvent = new UserEvent(userDto);
applicationContext.publishEvent(userEvent);
return String.format("用户%s注册成功,并赠送了100元优惠券", userDto.getName());
}
}
2 注解方式
场景:用户注册成功后,给用户发送邮件、短信通知
2.1 创建事件
继承ApplicationEvent,重新事件构造方法
2.1.1 创建发送邮件事件
package com.per.listener.e2;
import org.springframework.context.ApplicationEvent;
/**
* @Title SendMailEvent 发送邮件事件
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public class SendMailEvent extends ApplicationEvent {
public SendMailEvent(Object source) {
super(source);
}
}
2.1.2 创建发送短信事件
package com.per.listener.e2;
import org.springframework.context.ApplicationEvent;
/**
* @Title SendShortMsg 发送短信事件
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public class SendMsgEvent extends ApplicationEvent {
public SendMsgEvent(Object source) {
super(source);
}
}
2.2 创建事件监听器
定义事件执行的方法,使用注解@EventListener标注方法,使用classes属性指定方法对应的事件
package com.per.listener.e2;
import com.per.domain.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* @Title UserE2Listener
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Component
@Slf4j
public class UserE2Listener {
/**
* 发送邮件
* @param sendMailEvent 发送邮件事件
*/
@EventListener(classes = SendMailEvent.class)
@Order(1)
public void sendMail(SendMailEvent sendMailEvent){
UserDto userDto = (UserDto) sendMailEvent.getSource();
log.info("发送邮件给用户{} ...【邮件】恭喜你注册成功", userDto.getName());
}
/**
* 发送短信
* @param sendMsgEvent 发送短信事件
*/
@EventListener(classes = SendMsgEvent.class)
@Order(2)
public void sendMsg(SendMsgEvent sendMsgEvent){
UserDto userDto = (UserDto) sendMsgEvent.getSource();
log.info("发送短信给用户{} ...【短信】恭喜你注册成功", userDto.getName());
}
}
2.3 发布事件
引入ApplicationEventPublisher,调用publishEvent方法发布事件
package com.per.service.impl;
import com.per.domain.UserDto;
import com.per.listener.e2.SendMailEvent;
import com.per.listener.e2.SendMsgEvent;
import com.per.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
/**
* @Title UserServiceImpl
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
private ApplicationEventPublisher publisher;
@Override
public String userRegister1(UserDto userDto) {
log.info("用户{}注册成功,注册信息: {}", userDto.getName(), userDto.toString());
// 发送邮件
SendMailEvent sendMailEvent = new SendMailEvent(userDto);
publisher.publishEvent(sendMailEvent);
// 发送短息
SendMsgEvent sendMsgEvent = new SendMsgEvent(userDto);
publisher.publishEvent(sendMsgEvent);
return String.format("用户%s注册成功,并发送邮件和短信通知", userDto.getName());
}
}
3 项目使用案例
场景:用户注册成功,给用户发送邮件、短信通知
3.1 创建事件父类
package com.per.listener.e3.event;
/**
* @Title AbstractEvent 所有事件父类
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public abstract class AbstractEvent {
/**
* 事件源
*/
protected Object source;
public AbstractEvent(Object source) {
this.source = source;
}
/**
* 获取事件源
*
* @return
*/
public Object getSource() {
return source;
}
/**
* 设置事件源
*
* @param source
*/
public void setSource(Object source) {
this.source = source;
}
}
3.2 创建监听器接口
package com.per.listener.e3.listener;
import com.per.listener.e3.event.AbstractEvent;
/**
* @Title EventListener 事件监听器接口
* @ProjectName spring-boot-demo
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public interface EventListener<E extends AbstractEvent> {
/**
* 处理事件
*
* @param event 要处理的事件
*/
void onEvent(E event);
}
3.3 创建事件监听器管理类
package com.per.listener.e3.listener;
import com.per.listener.e3.event.AbstractEvent;
/**
* @Title EventListenerManager 事件监听器管理类
* @ProjectName spring-boot-demo
* @Description 1.负责事件监听器的管理(注册监听器&移除监听器,将事件和监听器关联起来)
* 2.负责事件的广播(将事件广播给所有的监听器,对该事件感兴趣的监听器会处理该事件)
* @Author Lee
* @Date 2024-01-17
*/
public interface EventListenerManager {
/**
* 广播事件给所有监听器
*
* @param event 事件
*/
void pushEvent(AbstractEvent event);
/**
* 添加一个事件监听器
*
* @param listener 事件监听器
*/
void addListener(EventListener<?> listener);
/**
* 删除一个事件监听器
*
* @param listener 事件监听器
*/
void removeListener(EventListener<?> listener);
}
3.4 创建事件监听器的简单实现
package com.per.listener.e3.listener.impl;
import com.per.listener.e3.event.AbstractEvent;
import com.per.listener.e3.listener.EventListener;
import com.per.listener.e3.listener.EventListenerManager;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Title SimpleEventListener 事件广播器的简单实现
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public class SimpleEventListener implements EventListenerManager {
private Map<Class<?>, List<EventListener>> eventListenerMap = new ConcurrentHashMap<>();
@Override
public void pushEvent(AbstractEvent event) {
List<EventListener> eventListeners = this.eventListenerMap.get(event.getClass());
if (eventListeners != null) {
for (EventListener eventListener : eventListeners) {
// 执行事件
eventListener.onEvent(event);
}
}
}
@Override
public void addListener(EventListener<?> listener) {
Class<?> eventType = this.getEventType(listener);
// 查询map中事件对应的监听器
List<EventListener> eventListeners = this.eventListenerMap.get(eventType);
if (eventListeners == null) {
// 事件对应的监听器集合为空,保存事件和监听器到map中,key:事件 value:空的监听器集合
eventListeners = new ArrayList<>();
this.eventListenerMap.put(eventType, eventListeners);
}
// 事件对应的监听器集合不为空,添加监听器到事件对应的监听器集合中
eventListeners.add(listener);
}
@Override
public void removeListener(EventListener<?> listener) {
Class<?> eventType = this.getEventType(listener);
// 查询map中事件对应的监听器
List<EventListener> eventListeners = this.eventListenerMap.get(eventType);
if (eventListeners != null) {
// 事件对应的监听器集合不为空,从事件对应的监听器集中删除当前监听
eventListeners.remove(listener);
}
}
protected Class<?> getEventType(EventListener eventListener) {
// 获取直接实现eventListener接口的类或接口的Type
ParameterizedType parameterizedType = (ParameterizedType) eventListener.getClass().getGenericInterfaces()[0];
// 获取EventListener中泛型的实际类型
Type eventType = parameterizedType.getActualTypeArguments()[0];
return (Class<?>) eventType;
}
}
3.5 创建用户注册事件
package com.per.listener.e3.event;
import com.per.domain.UserDto;
/**
* @Title RegisterSuccessEvent 用户注册成功事件
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
public class RegisterSuccessEvent extends AbstractEvent {
/**
* 用户信息
*/
private UserDto userDto;
/**
* 用户注册成功事件
*
* @param source 事件源
* @param userDto 用户信息
*/
public RegisterSuccessEvent(Object source, UserDto userDto) {
super(source);
this.userDto = userDto;
}
public UserDto getUserDto() {
return userDto;
}
public void setUserDto(UserDto userDto) {
this.userDto = userDto;
}
}
3.6 创建用户注册服务
package com.per.service.impl;
import com.per.domain.UserDto;
import com.per.listener.e3.event.RegisterSuccessEvent;
import com.per.listener.e3.listener.EventListenerManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @Title UserRegisterService 用户注册成功服务
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Slf4j
public class UserRegisterService {
/**
* 事件发布者
*/
@Autowired
private EventListenerManager eventListenerManager;
/**
* 用户注册
*
* @param userDto 用户信息
*/
public void registerUser(UserDto userDto) {
log.info("用户{}注册成功", userDto.getName());
// 执行其他监听事件
this.eventListenerManager.pushEvent(new RegisterSuccessEvent(this, userDto));
}
public EventListenerManager getEventListenerManager() {
return eventListenerManager;
}
public void setEventListenerManager(EventListenerManager eventListenerManager) {
this.eventListenerManager = eventListenerManager;
}
}
3.7 创建事件监听配置类
package com.per.listener.e3.config;
import com.per.listener.e3.listener.EventListener;
import com.per.listener.e3.listener.EventListenerManager;
import com.per.listener.e3.listener.impl.SimpleEventListener;
import com.per.service.impl.UserRegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Title EventListenerConfig
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Configuration
@Component
public class EventListenerConfig {
/**
* 注册一个事件发布者
*
* @param eventListeners 事件
* @return
*/
@Bean
@Autowired(required = false) // 当eventListeners不存在时不抛出异常
public EventListenerManager eventListenerManager(List<EventListener> eventListeners) {
EventListenerManager eventListenerManager = new SimpleEventListener();
if (eventListeners != null) {
eventListeners.forEach(eventListener -> eventListenerManager.addListener(eventListener));
}
return eventListenerManager;
}
/**
* 注册一个用户注册服务
*
* @param eventListenerManager
* @return
*/
@Bean
public UserRegisterService userRegisterService(EventListenerManager eventListenerManager) {
UserRegisterService userRegisterService = new UserRegisterService();
userRegisterService.setEventListenerManager(eventListenerManager);
return userRegisterService;
}
}
3.8 创建发送邮件服务
package com.per.service.impl;
import com.per.listener.e3.event.RegisterSuccessEvent;
import com.per.listener.e3.listener.EventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Title UserSendMailService 用户发送邮件服务
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Component
@Slf4j
public class UserSendMailService implements EventListener<RegisterSuccessEvent> {
@Override
public void onEvent(RegisterSuccessEvent event) {
log.info("给用户{}发送邮件,内容:恭喜你注册成功", event.getUserDto().getName());
}
}
3.9 创建发送短信服务
package com.per.service.impl;
import com.per.listener.e3.event.RegisterSuccessEvent;
import com.per.listener.e3.listener.EventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Title UserSendMsgService 用户发送短信服务
* @Description TODO
* @Author Lee
* @Date 2024-01-17
*/
@Component
@Slf4j
public class UserSendMsgService implements EventListener<RegisterSuccessEvent> {
@Override
public void onEvent(RegisterSuccessEvent event) {
log.info("给用户{}发送短息,短信内容:恭喜你注册成功", event.getUserDto().getName());
}
}
3.10 调用用户注册服务
/**
* 用户注册成功后发送邮件、发送短信
*
* @return
*/
@RequestMapping(value = "register", method = RequestMethod.GET)
public String register() {
UserDto userDto = new UserDto(11, "李四", "男");
userRegisterService.registerUser(userDto);
return "SUCCESS";
}
3.11 调用赠送优惠券服务(扩展)
新增场景:增加一个赠送优惠券业务
package com.per.service.impl;
import com.per.listener.e3.event.RegisterSuccessEvent;
import com.per.listener.e3.listener.EventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Title SendUserCouponsService 发送优惠券服务
* @Description TODO
* @Author Lee
* @Date 2024-01-20
*/
@Component
@Slf4j
public class SendUserCouponsService implements EventListener<RegisterSuccessEvent> {
@Override
public void onEvent(RegisterSuccessEvent event) {
log.info("给用户{}发送100元优惠券", event.getUserDto().getName());
}
}
4 拓展
4.1 控制发送邮件、短信、优惠券服务的执行顺序
可以通过@Order控制服务的加载顺序实现
原文地址:https://blog.csdn.net/songdancer/article/details/135708316
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!