ApplicationEventPublisherAware事件
2019-07-05 本文已影响0人
可可西里的星星
ApplicationEventPublisherAware事件发布详解
为了达到解耦的目的,一个类应当只做一件事,例如,用户进行注册时,需要创建注册相关的类,来完成注册事务。但是,如果注册成功时,还需要发送验证邮件,以及手机校验码,很多人为了方便,直接在注册类中将发送邮件和发送短信的代码一并写入。这样做会导致后面维护的困难,耦合性高。
我们可以通过事件发布来达到解耦的目的,事件的原理如下。
事件的发布者发布事件,事件的监听这对对应的事件进行监听,当监听到对应的事件时,就会触发调用相关的方法。因此,在事件处理中,事件是核心,是事件发布者和事件监听者的桥梁。
对应到上面的案例,我们可以在用户注册成功后发布事件,事件监听者监听到用户注册成功的事件后,触发发送邮件和发送短信的业务。由于要触发发送邮件和短信,因此要从事件发布者那里获取对应的邮件地址和手机号码,而这些信息是通过事件这个桥梁进行连接的,所以,事件中必须包含邮件地址和手机号码这两个属性。
分析了以上过程后我们开始编写代码:
1.springboot框架搭建:
1.1 pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.stu</groupId> <artifactId>springBootEvent</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
1.2properties文件配置:
server.port=9898server.servlet.context-path=/listener
1.3启动类:
package com.stu; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; @SpringBootApplication@RestControllerpublic class ListenerApplication { public static void main(String[] args) { SpringApplication.run(ListenerApplication.class, args); } @RequestMapping("/") public String healthyCheck() { return "Ok"; }}
2.事件类:由于需要发送邮件和短信,因此需要封装邮件地址和手机号码到事件类中,为了方便,直接将用户注册填写的信息封装成User类,并将该类直接作为事件的属性。
package com.stu.event; import org.springframework.context.ApplicationEvent; import com.stu.entity.User; public class UserRegisterEvent extends ApplicationEvent { private static final long serialVersionUID = -5481658020206295565L; private User user; //谁发布的这个事件,souce就是谁(对象) public UserRegisterEvent(Object source, User user) { super(source); this.user = user; } public User getUser() { return user; } }
3. Controller层:封装用户注册的参数为User类,并调用service进行注册
package com.stu.controller; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; import com.stu.entity.User;import com.stu.service.UserRegisterService; @RestController@RequestMapping("/user")public class UserRegisterController { @Autowired private UserRegisterService userRegisterService; @RequestMapping("/register") public String register(User user) { //进行注册 userRegisterService.register(user); return "[controller]注册用户成功!"; } }
4.Service层:执行用户注册,并发布事件
package com.stu.service; import org.springframework.context.ApplicationEventPublisher;import org.springframework.context.ApplicationEventPublisherAware;import org.springframework.stereotype.Service; import com.stu.entity.User;import com.stu.event.UserRegisterEvent; @Servicepublic class UserRegisterService implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; public boolean register(User user) { //用户注册 System.out.println("[service]用户[" + user + "]注册成功!"); //消息发布 applicationEventPublisher.publishEvent(new UserRegisterEvent(this, user)); return true; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; }}
5.事件监听:监听到事件发布后,自动执行onApplicationEvent方法,所以该类需要有IOC来管理,类上要加@Component注解
package com.stu.listener; import org.springframework.context.ApplicationListener;import org.springframework.stereotype.Component; import com.stu.event.UserRegisterEvent; @Componentpublic class EventListener implements ApplicationListener<UserRegisterEvent> { @Override public void onApplicationEvent(UserRegisterEvent event) { //发邮件 System.out.println("正在发送邮件至: " + event.getUser().getEmail()); //发短信 System.out.println("正在发短信到: " + event.getUser().getPhoneNum()); }}
6.实体类:
package com.stu.entity; public class User { private Integer id; private String name; private String phoneNum; private String email; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", phoneNum=" + phoneNum + ", email=" + email + "]"; } }
代码写好之后访问地址:http://localhost:9898/listener/user/register?id=1&name=john&phoneNum=13111111111&email=123@163.com可以得到以下结果:
控制台:
[service]用户[User [id=1, name=john, phoneNum=13111111111, email=123@163.com]]注册成功!
正在发送邮件至: 123@163.com
正在发短信到: 13111111111
页面显示:
[controller]注册用户成功!