重构侦听器模块改为事件订阅发布机制

This commit is contained in:
click33 2022-08-20 02:44:01 +08:00
parent ab0776ecc1
commit ce5b46f9a1
10 changed files with 322 additions and 55 deletions

View File

@ -13,8 +13,6 @@ import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.json.SaJsonTemplateDefaultImpl;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.listener.SaTokenListenerDefaultImpl;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.sign.SaSignTemplateDefaultImpl;
import cn.dev33.satoken.stp.StpInterface;
@ -140,24 +138,6 @@ public class SaManager {
return SaTokenContextDefaultImpl.defaultContext;
}
/**
* 侦听器 Bean
*/
private volatile static SaTokenListener saTokenListener;
public static void setSaTokenListener(SaTokenListener saTokenListener) {
SaManager.saTokenListener = saTokenListener;
}
public static SaTokenListener getSaTokenListener() {
if (saTokenListener == null) {
synchronized (SaManager.class) {
if (saTokenListener == null) {
setSaTokenListener(new SaTokenListenerDefaultImpl());
}
}
}
return saTokenListener;
}
/**
* 临时令牌验证模块 Bean
*/

View File

@ -0,0 +1,218 @@
package cn.dev33.satoken.listener;
import java.util.ArrayList;
import java.util.List;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.SaLoginModel;
/**
* Sa-Token 事件发布器
*
* @author kong
* @since: 2022-8-19
*/
public class SaTokenEventRelease {
// --------- 注册侦听器
private static List<SaTokenListener> listenerList = new ArrayList<>();
static {
// 默认添加控制台日志侦听器
listenerList.add(new SaTokenListenerForConsolePrint());
}
/**
* 获取已注册的所有侦听器
* @return /
*/
public static List<SaTokenListener> getListenerList() {
return listenerList;
}
/**
* 重置侦听器集合
* @param listenerList /
*/
public static void setListenerList(List<SaTokenListener> listenerList) {
if(listenerList == null) {
throw new SaTokenException("重置的侦听器集合不可以为空");
}
SaTokenEventRelease.listenerList = listenerList;
}
/**
* 注册一个侦听器
* @param listener /
*/
public static void registerListener(SaTokenListener listener) {
if(listener == null) {
throw new SaTokenException("注册的侦听器不可以为空");
}
listenerList.add(listener);
}
/**
* 注册一组侦听器
* @param listenerList /
*/
public static void registerListenerList(List<SaTokenListener> listenerList) {
if(listenerList == null) {
throw new SaTokenException("注册的侦听器不可以为空");
}
for (SaTokenListener listener : listenerList) {
if(listener == null) {
throw new SaTokenException("注册的侦听器不可以为空");
}
}
SaTokenEventRelease.listenerList.addAll(listenerList);
}
/**
* 移除一个侦听器
* @param listener /
*/
public static void removeListener(SaTokenListener listener) {
listenerList.remove(listener);
}
/**
* 移除指定类型的所有侦听器
* @param cls /
*/
public static void removeListener(Class<? extends SaTokenListener> cls) {
ArrayList<SaTokenListener> listenerListCopy = new ArrayList<>(listenerList);
for (SaTokenListener listener : listenerListCopy) {
if(cls.isAssignableFrom(listener.getClass())) {
listenerList.remove(listener);
}
}
}
/**
* 清空所有已注册的侦听器
*/
public static void clearListener() {
listenerList.clear();
}
/**
* 判断是否已经注册了指定侦听器
* @param listener /
* @return /
*/
public static boolean hasListener(SaTokenListener listener) {
return listenerList.contains(listener);
}
/**
* 判断是否已经注册了指定类型的侦听器
* @param cls /
* @return /
*/
public static boolean hasListener(Class<? extends SaTokenListener> cls) {
for (SaTokenListener listener : listenerList) {
if(cls.isAssignableFrom(listener.getClass())) {
return true;
}
}
return false;
}
// --------- 事件发布
/**
* 每次登录时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue 本次登录产生的 token
* @param loginModel 登录参数
*/
public static void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
for (SaTokenListener listener : listenerList) {
listener.doLogin(loginType, loginId, tokenValue, loginModel);
}
}
/**
* 每次注销时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public static void doLogout(String loginType, Object loginId, String tokenValue) {
for (SaTokenListener listener : listenerList) {
listener.doLogout(loginType, loginId, tokenValue);
}
}
/**
* 每次被踢下线时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public static void doKickout(String loginType, Object loginId, String tokenValue) {
for (SaTokenListener listener : listenerList) {
listener.doKickout(loginType, loginId, tokenValue);
}
}
/**
* 每次被顶下线时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public static void doReplaced(String loginType, Object loginId, String tokenValue) {
for (SaTokenListener listener : listenerList) {
listener.doReplaced(loginType, loginId, tokenValue);
}
}
/**
* 每次被封禁时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param disableTime 封禁时长单位:
*/
public static void doDisable(String loginType, Object loginId, long disableTime) {
for (SaTokenListener listener : listenerList) {
listener.doDisable(loginType, loginId, disableTime);
}
}
/**
* 每次被解封时触发
* @param loginType 账号类别
* @param loginId 账号id
*/
public static void doUntieDisable(String loginType, Object loginId) {
for (SaTokenListener listener : listenerList) {
listener.doUntieDisable(loginType, loginId);
}
}
/**
* 每次创建Session时触发
* @param id SessionId
*/
public static void doCreateSession(String id) {
for (SaTokenListener listener : listenerList) {
listener.doCreateSession(id);
}
}
/**
* 每次注销Session时触发
* @param id SessionId
*/
public static void doLogoutSession(String id) {
for (SaTokenListener listener : listenerList) {
listener.doLogoutSession(id);
}
}
}

View File

@ -7,11 +7,11 @@ import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token 侦听器的默认实现log打印
* Sa-Token 侦听器实现控制台 log 打印
* @author kong
*
*/
public class SaTokenListenerDefaultImpl implements SaTokenListener {
public class SaTokenListenerForConsolePrint implements SaTokenListener {
/**
* 每次登录时触发

View File

@ -0,0 +1,55 @@
package cn.dev33.satoken.listener;
import cn.dev33.satoken.stp.SaLoginModel;
/**
* Sa-Token 侦听器默认空实现
*
* <p> 对所有事件方法提供空实现方便开发者通过继承此类快速实现一个可用的侦听器
*
* @author kong
* @since: 2022-8-20
*/
public class SaTokenListenerForSimple implements SaTokenListener {
@Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
}
@Override
public void doLogout(String loginType, Object loginId, String tokenValue) {
}
@Override
public void doKickout(String loginType, Object loginId, String tokenValue) {
}
@Override
public void doReplaced(String loginType, Object loginId, String tokenValue) {
}
@Override
public void doDisable(String loginType, Object loginId, long disableTime) {
}
@Override
public void doUntieDisable(String loginType, Object loginId) {
}
@Override
public void doCreateSession(String id) {
}
@Override
public void doLogoutSession(String id) {
}
}

View File

@ -11,6 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.application.SaSetValueInterface;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@ -71,8 +72,8 @@ public class SaSession implements SaSetValueInterface, Serializable {
public SaSession(String id) {
this.id = id;
this.createTime = System.currentTimeMillis();
// $$ 通知监听器
SaManager.getSaTokenListener().doCreateSession(id);
// $$ 发布事件
SaTokenEventRelease.doCreateSession(id);
}
/**
@ -231,8 +232,8 @@ public class SaSession implements SaSetValueInterface, Serializable {
/** 注销Session (从持久库删除) */
public void logout() {
SaManager.getSaTokenDao().deleteSession(this.id);
// $$ 通知监听器
SaManager.getSaTokenListener().doLogoutSession(id);
// $$ 发布事件
SaTokenEventRelease.doLogoutSession(id);
}
/** 当Session上的tokenSign数量为零时注销会话 */

View File

@ -1,5 +1,10 @@
package cn.dev33.satoken.stp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
@ -21,17 +26,13 @@ import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.exception.NotSafeException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Sa-Token 权限认证逻辑实现类
* @author kong
@ -362,8 +363,8 @@ public class StpLogic {
// 写入 [token-last-activity]
setLastActivityToNow(tokenValue);
// $$ 通知监听器账号xxx 登录成功
SaManager.getSaTokenListener().doLogin(loginType, id, tokenValue, loginModel);
// $$ 发布事件账号xxx 登录成功
SaTokenEventRelease.doLogin(loginType, id, tokenValue, loginModel);
// 检查此账号会话数量是否超出最大值
if(config.getMaxLoginCount() != -1) {
@ -427,7 +428,8 @@ public class StpLogic {
// 删除Token-Id映射 & 清除Token-Session
deleteTokenToIdMapping(tokenValue);
deleteTokenSession(tokenValue);
SaManager.getSaTokenListener().doLogout(loginType, loginId, tokenValue);
// $$ 发布事件指定账号注销
SaTokenEventRelease.doLogout(loginType, loginId, tokenValue);
}
// 注销 Session
session.logoutByTokenSignCountToZero();
@ -463,7 +465,8 @@ public class StpLogic {
// 删除Token-Id映射 & 清除Token-Session
deleteTokenToIdMapping(tokenValue);
deleteTokenSession(tokenValue);
SaManager.getSaTokenListener().doLogout(loginType, loginId, tokenValue);
// $$ 发布事件指定账号注销
SaTokenEventRelease.doLogout(loginType, loginId, tokenValue);
}
// 注销 Session
session.logoutByTokenSignCountToZero();
@ -492,8 +495,8 @@ public class StpLogic {
return;
}
// $$ 通知监听器某某Token注销下线了
SaManager.getSaTokenListener().doLogout(loginType, loginId, tokenValue);
// $$ 发布事件某某Token注销下线了
SaTokenEventRelease.doLogout(loginType, loginId, tokenValue);
// 4. 清理User-Session上的token签名 & 尝试注销User-Session
SaSession session = getSessionByLoginId(loginId, false);
@ -530,7 +533,7 @@ public class StpLogic {
clearLastActivity(tokenValue);
// 将此 token 标记为已被踢下线
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
SaManager.getSaTokenListener().doKickout(loginType, loginId, tokenValue);
SaTokenEventRelease.doKickout(loginType, loginId, tokenValue);
}
// 注销 Session
session.logoutByTokenSignCountToZero();
@ -558,8 +561,8 @@ public class StpLogic {
// 3. 给token打上标记被踢下线
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
// $$. 否则通知监听器某某Token被踢下线了
SaManager.getSaTokenListener().doKickout(loginType, loginId, tokenValue);
// $$. 发布事件某某Token被踢下线了
SaTokenEventRelease.doKickout(loginType, loginId, tokenValue);
// 4. 清理User-Session上的token签名 & 尝试注销User-Session
SaSession session = getSessionByLoginId(loginId, false);
@ -586,7 +589,7 @@ public class StpLogic {
clearLastActivity(tokenValue);
// 将此 token 标记为已被顶替
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
SaManager.getSaTokenListener().doReplaced(loginType, loginId, tokenValue);
SaTokenEventRelease.doReplaced(loginType, loginId, tokenValue);
}
}
}
@ -1651,8 +1654,8 @@ public class StpLogic {
// 标注为已被封禁
getSaTokenDao().set(splicingKeyDisable(loginId), DisableLoginException.BE_VALUE, disableTime);
// $$ 通知监听器
SaManager.getSaTokenListener().doDisable(loginType, loginId, disableTime);
// $$ 发布事件
SaTokenEventRelease.doDisable(loginType, loginId, disableTime);
}
/**
@ -1680,8 +1683,8 @@ public class StpLogic {
public void untieDisable(Object loginId) {
getSaTokenDao().delete(splicingKeyDisable(loginId));
// $$ 通知监听器
SaManager.getSaTokenListener().doUntieDisable(loginType, loginId);
// $$ 发布事件
SaTokenEventRelease.doUntieDisable(loginType, loginId);
}

View File

@ -2,12 +2,12 @@ package cn.dev33.satoken.jwt;
import java.util.Map;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.ApiDisabledException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.jwt.exception.SaJwtException;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
@ -98,8 +98,8 @@ public class StpLogicJwtForStateless extends StpLogic {
// ------ 2生成一个token
String tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout(), loginModel.getExtraData());
// $$ 通知监听器账号xxx 登录成功
SaManager.getSaTokenListener().doLogin(loginType, id, tokenValue, loginModel);
// $$ 发布事件账号xxx 登录成功
SaTokenEventRelease.doLogin(loginType, id, tokenValue, loginModel);
return tokenValue;
}

View File

@ -1,5 +1,7 @@
package cn.dev33.satoken.reactor.spring;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.PathMatcher;
@ -14,6 +16,7 @@ import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.id.SaIdTemplate;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.stp.StpInterface;
@ -82,11 +85,11 @@ public class SaBeanInject {
/**
* 注入侦听器Bean
*
* @param saTokenListener saTokenListener对象
* @param listenerList 侦听器集合
*/
@Autowired(required = false)
public void setSaTokenListener(SaTokenListener saTokenListener) {
SaManager.setSaTokenListener(saTokenListener);
public void setSaTokenListener(List<SaTokenListener> listenerList) {
SaTokenEventRelease.registerListenerList(listenerList);
}
/**

View File

@ -14,6 +14,7 @@ import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.id.SaIdTemplate;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.solon.model.SaContextForSolon;
@ -63,8 +64,10 @@ public class XPluginImp implements Plugin {
});
// 注入侦听器 Bean
// TODO这里需要改为注入一组 Bean
context.getWrapAsyn(SaTokenListener.class, bw->{
SaManager.setSaTokenListener(bw.raw());
// SaManager.setSaTokenListener(bw.raw());
SaTokenEventRelease.registerListener(bw.raw());
});
// 注入权限认证 Bean
@ -107,4 +110,5 @@ public class XPluginImp implements Plugin {
StpUtil.setStpLogic(bw.raw());
});
}
}

View File

@ -1,5 +1,7 @@
package cn.dev33.satoken.spring;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.PathMatcher;
@ -14,6 +16,7 @@ import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.id.SaIdTemplate;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventRelease;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.stp.StpInterface;
@ -82,11 +85,11 @@ public class SaBeanInject {
/**
* 注入侦听器Bean
*
* @param saTokenListener saTokenListener对象
* @param listenerList 侦听器集合
*/
@Autowired(required = false)
public void setSaTokenListener(SaTokenListener saTokenListener) {
SaManager.setSaTokenListener(saTokenListener);
public void setSaTokenListener(List<SaTokenListener> listenerList) {
SaTokenEventRelease.registerListenerList(listenerList);
}
/**