• 基于 ApplicationEvent 实现事件监听(进阶篇)


    基于 ApplicationEvent 实现事件监听(进阶篇)

    背景:

    	实现一个消息事件,需要同时发送短信通知和邮件通知,并且每个通知都是异步方式。
    
    • 1

    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;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2. 抽象事件通知服务类

    在该类的 onApplicationEvent 方法上面添加 @Async ,同时需要在启动类上添加 @EnableAsync,实现异步通知。
    
    • 1
    @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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3. 定义策略类(子类)

    3.1 邮件通知类

    @Slf4j
    @Component("emailMessage")
    public class EmailMessageImpl extends MessageEvenService {
    
        @Override
        public void processMsg(MyMessage msg) {
            log.info("Email 监听 处理消息:{}", JSONObject.toJSONString(msg));
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.2 短信通知类

    @Slf4j
    @Component("smsMessage")
    public class SMSMessageImpl extends MessageEvenService {
    
        @Override
        protected void processMsg(MyMessage msg) {
            log.info("SMS 监听 处理消息:{}", JSONObject.toJSONString(msg));
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4. 测试事件通知controller

    @RestController
    public class EventDemoController {
    
        @Autowired
        private EventDemoService eventDemoService;
    
    
        @GetMapping("/testEvent")
        public String testEvent() {
            eventDemoService.testEvent();
            return "OK";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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("*********** 结束推送消息事件 ***********");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    7. 测试效果

    浏览器访问 http://localhost:8888/demo/testEvent
    在这里插入图片描述

    8. 项目结构

    在这里插入图片描述

  • 相关阅读:
    Spring Bean的生命周期和扩展点源码解读
    软件开发流程
    Spring Task定时任务框架
    vue3前端调用后端接口实现批量删除
    (附源码)spring boot酒店管理平台 毕业设计 201010
    “轻松解决Linux应用程序无法访问的难题:关闭SELinux就对了!“
    数据结构:树的概念和结构
    UE4(unreal Engine)中使用蓝图类Actor创建开关门,并使用鼠标和键盘控制开关门
    【使用 Python 实现算法】01 语言特性
    Android 框架
  • 原文地址:https://blog.csdn.net/qq_42610605/article/details/127769824