事件最大的好处是,不需要在事件发生时立即处理其他事情,也就是不需要直接调用方法去做其他事情,而是发布一个事件,让事件监听者去处理,可以使用同步或者异步处理事件,达到代码解耦(不需要直接调用),也便于扩展(以后增加该事件处理只需要增加监听者即可)。
本示例为,当禁用用户时,将用户的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,达到异步效果。以上就是事件机制,不需要直接调用,以后如果再增加一个需求,比如禁用用户后将该用户加入黑名单,则增加一个监听者去处理即可。
浙公网安备 33010602011771号