v1.10.0新特性:查询所有会话

This commit is contained in:
shengzhang
2021-01-07 22:03:44 +08:00
parent a1ec710efd
commit 22826dac86
15 changed files with 418 additions and 43 deletions

View File

@@ -1,5 +1,7 @@
package cn.dev33.satoken.dao; package cn.dev33.satoken.dao;
import java.util.List;
import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.session.SaSession;
/** /**
@@ -8,14 +10,14 @@ import cn.dev33.satoken.session.SaSession;
*/ */
public interface SaTokenDao { public interface SaTokenDao {
/** 常量表示一个key永不过期 (在一个key被标注为永远不过期时返回此值) */ /** 常量表示一个key永不过期 (在一个key被标注为永远不过期时返回此值) */
public static final Long NEVER_EXPIRE = -1L; public static final Long NEVER_EXPIRE = -1L;
/** 常量,表示系统中不存在这个缓存 (在对不存在的key获取剩余存活时间时返回此值) */ /** 常量,表示系统中不存在这个缓存 (在对不存在的key获取剩余存活时间时返回此值) */
public static final Long NOT_VALUE_EXPIRE = -2L; public static final Long NOT_VALUE_EXPIRE = -2L;
// --------------------- token相关 ---------------------
/** /**
* 根据key获取value如果没有则返回空 * 根据key获取value如果没有则返回空
@@ -58,7 +60,9 @@ public interface SaTokenDao {
* @param timeout 过期时间 * @param timeout 过期时间
*/ */
public void updateTimeout(String key, long timeout); public void updateTimeout(String key, long timeout);
// --------------------- Session相关 ---------------------
/** /**
* 根据指定key的Session如果没有则返回空 * 根据指定key的Session如果没有则返回空
@@ -101,7 +105,17 @@ public interface SaTokenDao {
public void updateSessionTimeout(String sessionId, long timeout); public void updateSessionTimeout(String sessionId, long timeout);
// --------------------- 会话管理 ---------------------
/**
* 搜索数据
* @param prefix 前缀
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public List<String> searchData(String prefix, String keyword, int start, int size);
} }

View File

@@ -2,6 +2,7 @@ package cn.dev33.satoken.dao;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -10,6 +11,7 @@ import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaTaskUtil; import cn.dev33.satoken.util.SaTaskUtil;
import cn.dev33.satoken.util.SaTaskUtil.FunctionRunClass; import cn.dev33.satoken.util.SaTaskUtil.FunctionRunClass;
import cn.dev33.satoken.util.SaTokenInsideUtil;
/** /**
* sa-token持久层默认的实现类 , 基于内存Map * sa-token持久层默认的实现类 , 基于内存Map
@@ -207,6 +209,14 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
// --------------------- 会话管理
@Override
public List<String> searchData(String prefix, String keyword, int start, int size) {
return SaTokenInsideUtil.searchList(expireMap.keySet(), prefix, keyword, start, size);
}

View File

@@ -202,7 +202,6 @@ public class StpLogic {
} }
} }
/** /**
* 当前会话注销登录 * 当前会话注销登录
*/ */
@@ -219,7 +218,6 @@ public class StpLogic {
logoutByTokenValue(tokenValue); logoutByTokenValue(tokenValue);
} }
/** /**
* 指定token的会话注销登录 * 指定token的会话注销登录
* @param tokenValue 指定token * @param tokenValue 指定token
@@ -246,7 +244,6 @@ public class StpLogic {
session.logoutByTokenSignCountToZero(); session.logoutByTokenSignCountToZero();
} }
/** /**
* 指定loginId的会话注销登录踢人下线 * 指定loginId的会话注销登录踢人下线
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-2 * <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-2
@@ -287,7 +284,6 @@ public class StpLogic {
session.logoutByTokenSignCountToZero(); session.logoutByTokenSignCountToZero();
} }
// 查询相关 // 查询相关
/** /**
@@ -299,7 +295,6 @@ public class StpLogic {
return getLoginIdDefaultNull() != null; return getLoginIdDefaultNull() != null;
} }
/** /**
* 检验当前会话是否已经登录,如未登录,则抛出异常 * 检验当前会话是否已经登录,如未登录,则抛出异常
*/ */
@@ -307,7 +302,6 @@ public class StpLogic {
getLoginId(); getLoginId();
} }
/** /**
* 获取当前会话账号id, 如果未登录,则抛出异常 * 获取当前会话账号id, 如果未登录,则抛出异常
* @return 账号id * @return 账号id
@@ -342,7 +336,6 @@ public class StpLogic {
return loginId; return loginId;
} }
/** /**
* 获取当前会话登录id, 如果未登录,则返回默认值 * 获取当前会话登录id, 如果未登录,则返回默认值
* @param <T> 返回类型 * @param <T> 返回类型
@@ -369,7 +362,6 @@ public class StpLogic {
return (T)loginId; return (T)loginId;
} }
/** /**
* 获取当前会话登录id, 如果未登录则返回null * 获取当前会话登录id, 如果未登录则返回null
* @return 账号id * @return 账号id
@@ -393,7 +385,6 @@ public class StpLogic {
return loginId; return loginId;
} }
/** /**
* 获取当前会话登录id, 并转换为String * 获取当前会话登录id, 并转换为String
* @return 账号id * @return 账号id
@@ -402,7 +393,6 @@ public class StpLogic {
return String.valueOf(getLoginId()); return String.valueOf(getLoginId());
} }
/** /**
* 获取当前会话登录id, 并转换为int * 获取当前会话登录id, 并转换为int
* @return 账号id * @return 账号id
@@ -415,7 +405,6 @@ public class StpLogic {
return Integer.valueOf(String.valueOf(getLoginId())); return Integer.valueOf(String.valueOf(getLoginId()));
} }
/** /**
* 获取当前会话登录id, 并转换为long * 获取当前会话登录id, 并转换为long
* @return 账号id * @return 账号id
@@ -428,7 +417,6 @@ public class StpLogic {
return Long.valueOf(String.valueOf(getLoginId())); return Long.valueOf(String.valueOf(getLoginId()));
} }
/** /**
* 获取指定token对应的登录id如果未登录则返回 null * 获取指定token对应的登录id如果未登录则返回 null
* @param tokenValue token * @param tokenValue token
@@ -462,6 +450,14 @@ public class StpLogic {
return session; return session;
} }
/**
* 获取指定key的session, 如果session尚未创建则返回null
* @param sessionId sessionId
* @return session对象
*/
public SaSession getSessionBySessionId(String sessionId) {
return getSessionBySessionId(sessionId, false);
}
/** /**
* 获取指定loginId的session, 如果session尚未创建isCreate=是否新建并返回 * 获取指定loginId的session, 如果session尚未创建isCreate=是否新建并返回
@@ -473,7 +469,6 @@ public class StpLogic {
return getSessionBySessionId(getKeySession(loginId), isCreate); return getSessionBySessionId(getKeySession(loginId), isCreate);
} }
/** /**
* 获取指定loginId的session如果session尚未创建则新建并返回 * 获取指定loginId的session如果session尚未创建则新建并返回
* @param loginId 账号id * @param loginId 账号id
@@ -483,7 +478,6 @@ public class StpLogic {
return getSessionByLoginId(loginId, true); return getSessionByLoginId(loginId, true);
} }
/** /**
* 获取当前会话的session, 如果session尚未创建isCreate=是否新建并返回 * 获取当前会话的session, 如果session尚未创建isCreate=是否新建并返回
* @param isCreate 是否新建 * @param isCreate 是否新建
@@ -493,7 +487,6 @@ public class StpLogic {
return getSessionByLoginId(getLoginId(), isCreate); return getSessionByLoginId(getLoginId(), isCreate);
} }
/** /**
* 获取当前会话的session如果session尚未创建则新建并返回 * 获取当前会话的session如果session尚未创建则新建并返回
* @return 当前会话的session * @return 当前会话的session
@@ -505,7 +498,6 @@ public class StpLogic {
// =================== token专属session =================== // =================== token专属session ===================
/** /**
* 获取指定token的专属session如果session尚未创建isCreate代表是否新建并返回 * 获取指定token的专属session如果session尚未创建isCreate代表是否新建并返回
* @param tokenValue token值 * @param tokenValue token值
@@ -516,7 +508,6 @@ public class StpLogic {
return getSessionBySessionId(getKeyTokenSession(tokenValue), isCreate); return getSessionBySessionId(getKeyTokenSession(tokenValue), isCreate);
} }
/** /**
* 获取指定token的专属session如果session尚未创建则新建并返回 * 获取指定token的专属session如果session尚未创建则新建并返回
* @param tokenValue token值 * @param tokenValue token值
@@ -526,7 +517,6 @@ public class StpLogic {
return getSessionBySessionId(getKeyTokenSession(tokenValue), true); return getSessionBySessionId(getKeyTokenSession(tokenValue), true);
} }
/** /**
* 获取当前token的专属-session如果session尚未创建isCreate代表是否新建并返回 * 获取当前token的专属-session如果session尚未创建isCreate代表是否新建并返回
* @param isCreate 是否新建 * @param isCreate 是否新建
@@ -547,7 +537,6 @@ public class StpLogic {
return getSessionBySessionId(getKeyTokenSession(getTokenValue()), isCreate); return getSessionBySessionId(getKeyTokenSession(getTokenValue()), isCreate);
} }
/** /**
* 获取当前token的专属-session如果session尚未创建则新建并返回 * 获取当前token的专属-session如果session尚未创建则新建并返回
* @return session会话 * @return session会话
@@ -559,7 +548,6 @@ public class StpLogic {
// =================== [临时过期] 验证相关 =================== // =================== [临时过期] 验证相关 ===================
/** /**
* 写入指定token的 [最后操作时间] 为当前时间戳 * 写入指定token的 [最后操作时间] 为当前时间戳
* @param tokenValue 指定token * @param tokenValue 指定token
@@ -573,7 +561,6 @@ public class StpLogic {
SaTokenManager.getSaTokenDao().setValue(getKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()), getConfig().getTimeout()); SaTokenManager.getSaTokenDao().setValue(getKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()), getConfig().getTimeout());
} }
/** /**
* 清除指定token的 [最后操作时间] * 清除指定token的 [最后操作时间]
* @param tokenValue 指定token * @param tokenValue 指定token
@@ -589,7 +576,6 @@ public class StpLogic {
SaTokenManager.getSaTokenServlet().getRequest().removeAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY); SaTokenManager.getSaTokenServlet().getRequest().removeAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY);
} }
/** /**
* 检查指定token 是否已经[临时过期],如果已经过期则抛出异常 * 检查指定token 是否已经[临时过期],如果已经过期则抛出异常
* @param tokenValue 指定token * @param tokenValue 指定token
@@ -621,7 +607,6 @@ public class StpLogic {
request.setAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true); request.setAttribute(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
} }
/** /**
* 检查当前token 是否已经[临时过期],如果已经过期则抛出异常 * 检查当前token 是否已经[临时过期],如果已经过期则抛出异常
*/ */
@@ -629,7 +614,6 @@ public class StpLogic {
checkActivityTimeout(getTokenValue()); checkActivityTimeout(getTokenValue());
} }
/** /**
* 续签指定token(将 [最后操作时间] 更新为当前时间戳) * 续签指定token(将 [最后操作时间] 更新为当前时间戳)
* @param tokenValue 指定token * @param tokenValue 指定token
@@ -642,7 +626,6 @@ public class StpLogic {
SaTokenManager.getSaTokenDao().updateValue(getKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis())); SaTokenManager.getSaTokenDao().updateValue(getKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()));
} }
/** /**
* 续签当前token(将 [最后操作时间] 更新为当前时间戳) * 续签当前token(将 [最后操作时间] 更新为当前时间戳)
* <h1>请注意: 即时token已经 [临时过期] 也可续签成功, * <h1>请注意: 即时token已经 [临时过期] 也可续签成功,
@@ -653,7 +636,6 @@ public class StpLogic {
} }
// =================== 过期时间相关 =================== // =================== 过期时间相关 ===================
/** /**
@@ -965,6 +947,42 @@ public class StpLogic {
} }
// =================== 会话管理 ===================
/**
* 根据条件查询token
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return token集合
*/
public List<String> searchTokenValue(String keyword, int start, int size) {
return SaTokenManager.getSaTokenDao().searchData(getKeyTokenValue(""), keyword, start, size);
}
/**
* 根据条件查询SessionId
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public List<String> searchSessionId(String keyword, int start, int size) {
return SaTokenManager.getSaTokenDao().searchData(getKeySession(""), keyword, start, size);
}
/**
* 根据条件查询token专属Session的Id
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public List<String> searchTokenSessionId(String keyword, int start, int size) {
return SaTokenManager.getSaTokenDao().searchData(getKeyTokenSession(""), keyword, start, size);
}
// =================== 返回相应key =================== // =================== 返回相应key ===================
/** /**

View File

@@ -194,6 +194,15 @@ public class StpUtil {
return stpLogic.getSessionByLoginId(loginId, isCreate); return stpLogic.getSessionByLoginId(loginId, isCreate);
} }
/**
* 获取指定key的session, 如果session尚未创建则返回null
* @param sessionId sessionId
* @return session对象
*/
public static SaSession getSessionBySessionId(String sessionId) {
return stpLogic.getSessionBySessionId(sessionId);
}
/** /**
* 获取指定loginId的session如果session尚未创建则新建并返回 * 获取指定loginId的session如果session尚未创建则新建并返回
* @param loginId 账号id * @param loginId 账号id
@@ -439,5 +448,42 @@ public class StpUtil {
public static String getLoginDevice() { public static String getLoginDevice() {
return stpLogic.getLoginDevice(); return stpLogic.getLoginDevice();
} }
// =================== 会话管理 ===================
/**
* 根据条件查询token
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return token集合
*/
public static List<String> searchTokenValue(String keyword, int start, int size) {
return stpLogic.searchTokenValue(keyword, start, size);
}
/**
* 根据条件查询SessionId
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public static List<String> searchSessionId(String keyword, int start, int size) {
return stpLogic.searchSessionId(keyword, start, size);
}
/**
* 根据条件查询token专属Session的Id
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public static List<String> searchTokenSessionId(String keyword, int start, int size) {
return stpLogic.searchTokenSessionId(keyword, start, size);
}
} }

View File

@@ -1,9 +1,13 @@
package cn.dev33.satoken.util; package cn.dev33.satoken.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random; import java.util.Random;
/** /**
* sa-token 工具类 * sa-token 内部代码工具类
* @author kong * @author kong
* *
*/ */
@@ -49,4 +53,58 @@ public class SaTokenInsideUtil {
} }
/**
* 从集合里查询数据
* @param dataList 数据集合
* @param prefix 前缀
* @param keyword 关键字
* @param start 起始位置 (-1代表查询所有)
* @param size 获取条数
* @return 符合条件的新数据集合
*/
public static List<String> searchList(Collection<String> dataList, String prefix, String keyword, int start, int size) {
if(prefix == null) {
prefix = "";
}
if(keyword == null) {
keyword = "";
}
// 挑选出所有符合条件的
List<String> list = new ArrayList<String>();
Iterator<String> keys = dataList.iterator();
while (keys.hasNext()) {
String key = keys.next();
if(key.startsWith(prefix) && key.indexOf(keyword) > -1) {
list.add(key);
}
}
// 取指定段数据
return searchList(list, start, size);
}
/**
* 从集合里查询数据
* @param list 数据集合
* @param start 起始位置 (-1代表查询所有)
* @param size 获取条数
* @return 符合条件的新数据集合
*/
public static List<String> searchList(List<String> list, int start, int size) {
// 取指定段数据
if(start < 0) {
return list;
}
int end = start + size;
List<String> list2 = new ArrayList<String>();
for (int i = start; i < end; i++) {
if(i >= list.size()) {
return list2;
}
list2.add(list.get(i));
}
return list2;
}
} }

View File

@@ -1,6 +1,9 @@
package cn.dev33.satoken.dao; package cn.dev33.satoken.dao;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +18,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaTokenInsideUtil;
/** /**
* sa-token持久层的实现类, 基于redis (to jackson) * sa-token持久层的实现类, 基于redis (to jackson)
@@ -181,5 +185,15 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
public void updateSessionTimeout(String sessionId, long timeout) { public void updateSessionTimeout(String sessionId, long timeout) {
sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS); sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS);
} }
/**
* 搜索数据
*/
@Override
public List<String> searchData(String prefix, String keyword, int start, int size) {
Set<String> keys = stringRedisTemplate.keys(prefix + "*" + keyword + "*");
List<String> list = new ArrayList<String>(keys);
return SaTokenInsideUtil.searchList(list, start, size);
}
} }

View File

@@ -1,5 +1,8 @@
package cn.dev33.satoken.dao; package cn.dev33.satoken.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -11,6 +14,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaTokenInsideUtil;
/** /**
* sa-token持久层的实现类, 基于redis * sa-token持久层的实现类, 基于redis
@@ -162,5 +166,18 @@ public class SaTokenDaoRedis implements SaTokenDao {
public void updateSessionTimeout(String sessionId, long timeout) { public void updateSessionTimeout(String sessionId, long timeout) {
sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS); sessionRedisTemplate.expire(sessionId, timeout, TimeUnit.SECONDS);
} }
/**
* 搜索数据
*/
@Override
public List<String> searchData(String prefix, String keyword, int start, int size) {
Set<String> keys = stringRedisTemplate.keys(prefix + "*" + keyword + "*");
List<String> list = new ArrayList<String>(keys);
return SaTokenInsideUtil.searchList(list, start, size);
}
} }

View File

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.pj.util.AjaxJson;
import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException; import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException; import cn.dev33.satoken.exception.NotRoleException;

View File

@@ -0,0 +1,62 @@
package com.pj.test;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.pj.util.AjaxJson;
import com.pj.util.Ttime;
import cn.dev33.satoken.stp.StpUtil;
/**
* 压力测试
* @author kong
*
*/
@RestController
@RequestMapping("/s-test/")
public class StressTestController {
// 测试 浏览器访问: http://localhost:8081/s-test/login
// 测试前,请先将 is-read-cookie 配置为 false
@RequestMapping("login")
public AjaxJson login() {
// StpUtil.getTokenSession().logout();
// StpUtil.logoutByLoginId(10001);
// 循环10次 取平均时间
List<Double> list = new ArrayList<>();
for (int i = 10; i <= 1; i++) {
System.out.println("\n---------------------第" + i + "轮---------------------");
Ttime t = new Ttime().start();
// 每次登录的次数
for (int j = 1; j <= 10000; j++) {
StpUtil.setLoginId("1000" + j, "PC-" + j);
if(j % 1000 == 0) {
System.out.println("已登录:" + j);
}
}
t.end();
list.add((t.returnMs() + 0.0) / 1000);
System.out.println("" + i + "" + "用时:" + t.toString());
}
// System.out.println(((SaTokenDaoDefaultImpl)SaTokenManager.getSaTokenDao()).dataMap.size());
System.out.println("\n---------------------测试结果---------------------");
System.out.println(list.size() + "次测试: " + list);
double ss = 0;
for (int i = 0; i < list.size(); i++) {
ss += list.get(i);
}
System.out.println("平均用时: " + ss / list.size());
return AjaxJson.getSuccess();
}
}

View File

@@ -1,6 +1,7 @@
package com.pj.test; package com.pj.test;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@@ -8,6 +9,8 @@ import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.pj.util.AjaxJson;
import com.pj.util.Ttime;
import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
@@ -191,17 +194,7 @@ public class TestController {
// 返回 // 返回
return AjaxJson.getSuccess(); return AjaxJson.getSuccess();
} }
// 测试 浏览器访问: http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {
// StpUtil.getTokenSession().logout();
StpUtil.logoutByLoginId(10001);
return AjaxJson.getSuccess();
}
// 测试登录接口, 按照设备登录, 浏览器访问: http://localhost:8081/test/login2 // 测试登录接口, 按照设备登录, 浏览器访问: http://localhost:8081/test/login2
@RequestMapping("login2") @RequestMapping("login2")
public AjaxJson login2(@RequestParam(defaultValue="10001") String id, @RequestParam(defaultValue="PC") String device) { public AjaxJson login2(@RequestParam(defaultValue="10001") String id, @RequestParam(defaultValue="PC") String device) {
@@ -209,4 +202,30 @@ public class TestController {
return AjaxJson.getSuccess(); return AjaxJson.getSuccess();
} }
// 测试 浏览器访问: http://localhost:8081/test/searchSession
// 测试前,请先将 is-read-cookie 配置为 false
@RequestMapping("searchSession")
public AjaxJson searchSession() {
System.out.println("--------------");
Ttime t = new Ttime().start();
List<String> tokenValue = StpUtil.searchTokenValue("", 0, 10);
for (String v : tokenValue) {
// SaSession session = StpUtil.getSessionBySessionId(sid);
System.out.println(v);
}
System.out.println("用时:" + t.end().toString());
return AjaxJson.getSuccess();
}
// 测试 浏览器访问: http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {
StpUtil.getTokenSession().logout();
StpUtil.logoutByLoginId(10001);
return AjaxJson.getSuccess();
}
} }

View File

@@ -1,4 +1,4 @@
package com.pj.test; package com.pj.util;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;

View File

@@ -0,0 +1,63 @@
package com.pj.util;
/**
* 用于测试用时
* @author kong
*
*/
public class Ttime {
private long start=0; //开始时间
private long end=0; //结束时间
public static Ttime t = new Ttime(); //static快捷使用
/**
* 开始计时
* @return
*/
public Ttime start() {
start=System.currentTimeMillis();
return this;
}
/**
* 结束计时
*/
public Ttime end() {
end=System.currentTimeMillis();
return this;
}
/**
* 返回所用毫秒数
*/
public long returnMs() {
return end-start;
}
/**
* 格式化输出结果
*/
public void outTime() {
System.out.println(this.toString());
}
/**
* 结束并格式化输出结果
*/
public void endOutTime() {
this.end().outTime();
}
@Override
public String toString() {
return (returnMs() + 0.0) / 1000 + "s"; // 格式化为0.01s
}
}

View File

@@ -18,11 +18,14 @@ spring:
# token风格 # token风格
token-style: uuid token-style: uuid
# 是否从cookie里读取token
# is-read-cookie: false
# redis配置 # redis配置
redis: redis:
# Redis数据库索引默认为0 # Redis数据库索引默认为0
database: 1 database: 0
# Redis服务器地址 # Redis服务器地址
host: 127.0.0.1 host: 127.0.0.1
# Redis服务器连接端口 # Redis服务器连接端口
@@ -30,7 +33,7 @@ spring:
# Redis服务器连接密码默认为空 # Redis服务器连接密码默认为空
password: password:
# 连接超时时间(毫秒) # 连接超时时间(毫秒)
timeout: 1000ms timeout: 10000ms
lettuce: lettuce:
pool: pool:
# 连接池最大连接数 # 连接池最大连接数

View File

@@ -18,6 +18,7 @@
- [注解式鉴权](/use/at-check) - [注解式鉴权](/use/at-check)
- [花式token](/use/token-style) - [花式token](/use/token-style)
- [框架配置](/use/config) - [框架配置](/use/config)
- [会话治理](/use/search-session)
- **其它** - **其它**
- [常见问题](/more/common-questions) - [常见问题](/more/common-questions)

View File

@@ -0,0 +1,48 @@
# 会话治理
尽管框架将大部分操作提供了简易的封装,但在一些特殊场景下,我们仍需要绕过框架,直达数据底层进行一些操作 <br>
sa-token提供以下API助你直接操作会话列表
---
## 具体API
#### 查询所有token
``` java
StpUtil.searchTokenValue(String keyword, int start, int size);
```
#### 查询所有账号Session会话
``` java
StpUtil.searchSessionId(String keyword, int start, int size);
```
#### 查询所有令牌Session会话
``` java
StpUtil.searchTokenSessionId(String keyword, int start, int size);
```
#### 参数详解:
- `keyword`: 查询关键字只有包括这个字符串的token值才会被查询出来
- `start`: 数据开始处索引, 值为-1时代表一次性取出所有数据
- `size`: 要获取的数据条数
使用示例:
``` java
StpUtil.searchTokenValue("1000", 0, 10); // 查询value包括1000的所有token结果集从第0条开始返回10条
```
<br/>
#### 注意事项:
由于会话查询底层采用了遍历方式获取数据,当数据量过大时此操作将会比较耗时,有多耗时呢?这里提供一份参考数据:
- 单机模式下百万会话取出10条token平均耗时 `0.255s`
- Redis模式下百万会话取出10条token平均耗时 `3.322s`
请根据业务实际水平合理调用API