基于Spring接口实现用户行为的事件监听

在这里插入图片描述

说明

  1. 事件监听机制可以理解为是一种观察者模式,有数据发布者(事件源)和数据接受者(监听器);

  2. 在Java中,事件对象都是继承java.util.EventObject对象,事件监听器都是java.util.EventListener实例;

  3. 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事件监听有两种方式:

  1. 面向接口编程,实现ApplicationListener接口;
  2. 基于注解驱动,@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. 用户退出登录接口日志记录

通过 ApplicationEventPublisherpublishEvent 方法发布一个 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);
    }
}
  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值