事件最大的好处是,不需要在事件发生时立即处理其他事情,也就是不需要直接调用方法去做其他事情,而是发布一个事件,让事件监听者去处理,可以使用同步或者异步处理事件,达到代码解耦(不需要直接调用),也便于扩展(以后增加该事件处理只需要增加监听者即可)。

本示例为,当禁用用户时,将用户的token清除,然后给用户发送消息通知。使用了事件、异步操作

禁用用户,则发布一个事件对象,让两个事件处理方法分别去清除token和发送消息,一个同步,一个异步

1.编写事件对象

import lombok.AllArgsConstructor;
import lombok.Data;
@Data
// 表示生成一个全参的构造方法
@AllArgsConstructor
public class DisableUser {
    private Long userId;
}

2.启动类开启异步支持

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
// 开启异步支持
@EnableAsync
// 标记为启动类
@SpringBootApplication
public class Resource1Application {
    public static void main(String[] args) {
        SpringApplication.run(Resource1Application.class, args);
    }
}

3.编写事件处理方法

import com.chuwu.model.DisableUser;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

@Component
public class UserListener {
    /**
     * 禁用用户后,删除用户token,采用同步
     * condition条件,userId不为1才清除token,这里只是做示例,演示condition用法
     * @param disableUser 用户信息
     */
    @EventListener(value = DisableUser.class, condition = "#disableUser.getUserId() != '1L'")
    public void clearToken(DisableUser disableUser) {
        // 打出线程名称,看看是否异步操作
        System.out.println("====clearToken====" + Thread.currentThread().getName());
        System.out.println(disableUser.getUserId());
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 做清除token操作,前提是token是自定义生成的,和userId有关的,可以通过userId获取到这个用户的token的。这里省略。
    }
    /**
     * 禁用用户后给该用户发送消息,采用异步
     * @param disableUser 用户信息
     */
    @Async
    @EventListener(DisableUser.class)
    public void sendMessage(DisableUser disableUser) {
        // 打出线程名称,看看是否异步操作
        System.out.println("====sendMessage====" + Thread.currentThread().getName());
        System.out.println(disableUser.getUserId());
        // 做发送消息操作,这里省略
    }
}

4.发布事件

import com.chuwu.model.DisableUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Autowired
    ApplicationContext applicationContext;
    @GetMapping("/r/test")
    public void test() {
        System.out.println("====main====" + Thread.currentThread().getName());
        DisableUser disableUser = new DisableUser(3L);
        // 发布事件对象
        applicationContext.publishEvent(disableUser);
        System.out.println("====test end====");
    }
}

执行流程为,A线程执行TestController.test方法,然后执行到applicationContext.publishEvent(disableUser)后,A线程马上去做UserListener.clearToken,然后spring启动一个新线程B去执行UserListener.sendMessage,达到异步效果。以上就是事件机制,不需要直接调用,以后如果再增加一个需求,比如禁用用户后将该用户加入黑名单,则增加一个监听者去处理即可。

posted on 2021-06-01 11:01  chuwu  阅读(255)  评论(3)    收藏  举报