基于 ApplicationEvent 实现事件监听(进阶篇)
背景:
实现一个消息事件,需要同时发送短信通知和邮件通知,并且每个通知都是异步方式。
1. 事件类
public class MyMessageEvent extends ApplicationEvent {
private static final long serialVersionUID = -5481658020206295565L;
private MyMessage msg;
//谁发布的这个事件,souce就是谁(对象)
public MyMessageEvent(Object source, MyMessage msg) {
super(source);
this.msg = msg;
}
public MyMessage getMsg() {
return msg;
}
}
2. 抽象事件通知服务类
在该类的 onApplicationEvent 方法上面添加 @Async ,同时需要在启动类上添加 @EnableAsync,实现异步通知。
@Slf4j
@Service
public abstract class MessageEvenService implements ApplicationListener<MyMessageEvent> {
@Async
@Override
public void onApplicationEvent(MyMessageEvent event) {
this.processMsg(event.getMsg());
}
protected abstract void processMsg(MyMessage msg);
}
3. 定义策略类(子类)
3.1 邮件通知类
@Slf4j
@Component("emailMessage")
public class EmailMessageImpl extends MessageEvenService {
@Override
public void processMsg(MyMessage msg) {
log.info("Email 监听 处理消息:{}", JSONObject.toJSONString(msg));
}
}
3.2 短信通知类
@Slf4j
@Component("smsMessage")
public class SMSMessageImpl extends MessageEvenService {
@Override
protected void processMsg(MyMessage msg) {
log.info("SMS 监听 处理消息:{}", JSONObject.toJSONString(msg));
}
}
4. 测试事件通知controller
@RestController
public class EventDemoController {
@Autowired
private EventDemoService eventDemoService;
@GetMapping("/testEvent")
public String testEvent() {
eventDemoService.testEvent();
return "OK";
}
}
5. 测试事件通知service
@Service
@Slf4j
public class EventDemoServiceImpl implements EventDemoService {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void testEvent() {
log.info("*********** 开始推送消息事件 ***********");
MyMessage message = new MyMessage().setMessage("彩票中将啦").setMsgId("m123456").setNotifyId("u0000000");
applicationEventPublisher.publishEvent(new MyMessageEvent(this, message));
log.info("*********** 结束推送消息事件 ***********");
}
}
6. 配置线程池
@Configuration
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("user-rpt-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
7. 测试效果
浏览器访问 http://localhost:8888/demo/testEvent