前言
本节内容我们主要介绍一下springboot自定义事件的发布与订阅功能,一些特定应用场景下使用自定义事件发布功能,能大大降低我们代码的耦合性,使得我们应用程序的扩展更加方便。就本身而言,springboot的事件机制是通过观察者设计模式实现。通过ApplicationListener事件监听器实现事件的发布与订阅。我们以登录场景为例,假如用户登录之后,需要发送登录通知、发送邮件通知、发送签到通知,如果按照常规做法,我们可以顺序执行以上操作,但是使用springboot的事件机制,我们可以发布一个登录的事件消息,然后各自去消费登录这个事件消息,这样达到业务解耦的效果。
正文
①创建一个事件发布器,用于发送自定义的消息事件
- 实现代码:通过实现ApplicationEventPublisherAware 接口
package com.yundi.isbc.event.publish; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.stereotype.Component; @Component public class MyApplicationEventPublisherAware implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * 消息事件发布 * @param applicationEvent */ public void publishEvent(ApplicationEvent applicationEvent) { applicationEventPublisher.publishEvent(applicationEvent); } }
②创建一个登录的自定义消息事件
- 实现代码:通过继承ApplicationEvent事件实现自定义消息事件
package com.yundi.isbc.event.publish; import com.yundi.isbc.entity.User; import org.springframework.context.ApplicationEvent; public class LoginApplicationEvent extends ApplicationEvent { public LoginApplicationEvent(User user) { super(user); } }
③创建一个用户实体类,用于数据的传输
- 实现代码
package com.yundi.isbc.entity; import lombok.Data; import lombok.experimental.Accessors; @Accessors(chain = true) @Data public class User { /** * 用户名 */ private String username; /** * 密码 */ private String password; }
④创建一个控制器LoginController,用于登录业务处理,并发布登录事件
- 实现代码
package com.yundi.isbc.controller; import com.yundi.isbc.entity.User; import com.yundi.isbc.event.publish.LoginApplicationEvent; import com.yundi.isbc.event.publish.MyApplicationEventPublisherAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/index") public class LoginController { @Autowired private MyApplicationEventPublisherAware myApplicationEventPublisherAware; @GetMapping("login") public String login() { //发布登录事件 myApplicationEventPublisherAware.publishEvent(new LoginApplicationEvent(new User() .setUsername("xiaoming").setPassword("123456"))); //todo 主流程业务处理 return "ok"; } }
- 代码说明
⑤ 通过实现ApplicationListener接口,实现登录通知消息的消费,并做相关的业务处理
- 实现代码
package com.yundi.isbc.event.describe; import com.yundi.isbc.entity.User; import com.yundi.isbc.event.publish.LoginApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Service; @Service public class LoginNotifyListen implements ApplicationListener<LoginApplicationEvent> { public void accumulateLogin(User user) { System.out.println("=======登录业务======" + user); } @Override public void onApplicationEvent(LoginApplicationEvent event) { System.out.println("===============收到登录通知事件==================="); User user = (User) event.getSource(); accumulateLogin(user); } }
⑥通过@EventListener方式订阅消息,实现邮件业务处理,该种方式更加灵活,不用实现ApplicationListener接口
- 实现代码
package com.yundi.isbc.event.describe; import com.yundi.isbc.entity.User; import com.yundi.isbc.event.publish.LoginApplicationEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @Service public class MailNotifyListen { public void mailNotify(User user) { System.out.println("=======邮件业务======" + user); } @EventListener public void onLoginEvent(LoginApplicationEvent loginApplicationEvent) { System.out.println("===============收到登录通知事件==================="); User user = (User) loginApplicationEvent.getSource(); mailNotify(user); } }
⑦通过@EventListener方式订阅消息,实现签到业务处理
-实现代码
package com.yundi.isbc.event.describe; import com.yundi.isbc.entity.User; import com.yundi.isbc.event.publish.LoginApplicationEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @Service public class SignNotifyListen { public void signNotify(User user) { System.out.println("=======签到业务======" + user); } @EventListener public void onLoginEvent(LoginApplicationEvent loginApplicationEvent) { System.out.println("===============收到登录通知事件==================="); User user = (User) loginApplicationEvent.getSource(); signNotify(user); } }
⑧验证结果,访问登录接口,查看控制台,所有订阅事件的业务都能正常订阅消费
结语
关于springboot自定义事件的发布和订阅的内容到这里就结束了,我们下期见。。。。。。