说明
-
事件监听机制可以理解为是一种观察者模式,有数据发布者(事件源)和数据接受者(监听器);
-
在Java中,事件对象都是继承java.util.EventObject对象,事件监听器都是java.util.EventListener实例;
-
EventObject对象不提供默认构造器,需要外部传递source参数,即用于记录并跟踪事件的来源;
Spring事件
Spring事件对象为ApplicationEvent,继承EventObject,源码如下:
public abstract class ApplicationEvent extends EventObject {
/**
* Create a new ApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
}
Spring事件监听器为ApplicationListener,继承EventListener, 源码如下:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
实现Spring事件监听有两种方式:
- 面向接口编程,实现ApplicationListener接口;
- 基于注解驱动,@EventListener(Spring自定义的注解);
这里只说明用接口实现
核心代码
1. 自定义事件对象继承 ApplicationEvent
public class UserEvent extends ApplicationEvent {
//UserEventLog 用于存储用户行为
private final UserEventLog userEventLog;
/**
* Instantiates a new User event.
*
* @param userEventLog the user event log
*/
public UserEvent(final UserEventLog userEventLog) {
super(userEventLog);
this.userEventLog = userEventLog;
}
/**
* Gets user event log.
*
* @return the user event log
*/
public UserEventLog getUserEventLog() {
return userEventLog;
}
}
2. 创建 UserEventLog 用于存储用户行为
public class UserEventLog implements Serializable {
private static final long serialVersionUID = -3951198127152024633L;
public UserEventLog() {
}
public UserEventLog(Integer userId, String userName, String realName, Date createTime) {
this.userId = userId;
this.userName = userName;
this.realName = realName;
this.createTime = createTime;
}
private Integer id;
/**
* 用户id
*/
private Integer userId;
/**
* 用户名
*/
private String userName;
/**
* 真实姓名
*/
private String realName;
/**
* 内容
*/
private String content;
/**
* 时间
*/
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName == null ? null : realName.trim();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content == null ? null : content.trim();
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
3.注册用户监听器实现ApplicationListener接口
表示一个用户事件的监听器。当一个 UserEvent 被发布时,onApplicationEvent 方法将会被调用,然后将用户事件日志插入到数据库中。
@Component
public class UserLogListener implements ApplicationListener<UserEvent> {
private final UserEventLogService userEventLogService;
/**
* Instantiates a new User log listener.
*
* @param userEventLogService the user event log service
*/
@Autowired
public UserLogListener(UserEventLogService userEventLogService) {
this.userEventLogService = userEventLogService;
}
@Override
public void onApplicationEvent(UserEvent userEvent) {
userEventLogService.insertByFilter(userEvent.getUserEventLog());
}
}
4. 用户退出登录接口日志记录
通过 ApplicationEventPublisher
的 publishEvent
方法发布一个 UserEvent
事件,将用户注销事件通知给UserLogListener
监听器。监听器调用 onApplicationEvent
方法存入数据库。
eventPublisher.publishEvent(new UserEvent(userEventLog));
这行代码是用来通知已经注册了对 UserEvent
事件感兴趣的监听器。当事件发布时,Spring 框架会遍历所有注册的监听器,找到对应的监听器,并调用其 onApplicationEvent()
方法。
在监听器的 onApplicationEvent()
方法中,就可以编写具体的业务逻辑,来处理这个事件。因此,eventPublisher.publishEvent()
方法的作用是通知监听器,而具体的业务逻辑则是在监听器内执行。
ApplicationEventPublisher 是 Spring 框架中用于发布事件的接口。它定义了一个方法 publishEvent(),可以用来发布各种类型的事件到应用程序的事件系统中。
通过使用 ApplicationEventPublisher,可以将事件发布给注册了对应事件类型的监听器。当事件发布时,Spring 框架会自动调用所有对该事件感兴趣的监听器,并将事件传递给它们,以便执行相应的业务逻辑。
通过注入 ApplicationEventPublisher,可以在需要的时候发布自定义的事件,以实现不同组件之间的解耦和通信。
@Component
public class RestLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private final ApplicationEventPublisher eventPublisher;
private final UserService userService;
/**
* Instantiates a new Rest logout success handler.
*
* @param eventPublisher the event publisher
* @param userService the user service
*/
@Autowired
public RestLogoutSuccessHandler(ApplicationEventPublisher eventPublisher, UserService userService) {
this.eventPublisher = eventPublisher;
this.userService = userService;
}
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
org.springframework.security.core.userdetails.User springUser = (org.springframework.security.core.userdetails.User) authentication.getPrincipal();
if (null != springUser) {
User user = userService.getUserByUserName(springUser.getUsername());
UserEventLog userEventLog = new UserEventLog(user.getId(), user.getUserName(), user.getRealName(), new Date());
userEventLog.setContent(user.getUserName() + " 登出了系统");
eventPublisher.publishEvent(new UserEvent(userEventLog));
}
RestUtil.response(response, SystemCode.OK);
}
}