dao层默认实现增加定时清理过期数据功能

This commit is contained in:
shengzhang 2020-12-27 18:18:08 +08:00
parent 67abf576f0
commit 20f6bd7b3d
7 changed files with 153 additions and 13 deletions

View File

@ -55,6 +55,9 @@ public class SaTokenManager {
return saTokenDao;
}
public static void setSaTokenDao(SaTokenDao saTokenDao) {
if(SaTokenManager.saTokenDao != null && (SaTokenManager.saTokenDao instanceof SaTokenDaoDefaultImpl)) {
((SaTokenDaoDefaultImpl)SaTokenManager.saTokenDao).endRefreshTimer();
}
SaTokenManager.saTokenDao = saTokenDao;
}
public synchronized static void initSaTokenDao() {

View File

@ -46,6 +46,11 @@ public class SaTokenConfig {
* token风格
*/
private String tokenStyle = "uuid";
/**
* 默认dao层实现类中每次清理过期数据间隔的时间 (单位: ) 默认值30秒设置为-1代表不启动定时清理
*/
private int dataRefreshPeriod = 30;
/**
* 是否在初始化配置时打印版本字符画
@ -53,8 +58,7 @@ public class SaTokenConfig {
private Boolean isV = true;
/**
* @return tokenName
*/
@ -181,7 +185,20 @@ public class SaTokenConfig {
this.isV = isV;
}
/**
* @return dataRefreshPeriod
*/
public int getDataRefreshPeriod() {
return dataRefreshPeriod;
}
/**
* @param dataRefreshPeriod 要设置的 dataRefreshPeriod
*/
public void setDataRefreshPeriod(int dataRefreshPeriod) {
this.dataRefreshPeriod = dataRefreshPeriod;
}
/**
* 将对象转为String字符串
@ -190,8 +207,11 @@ public class SaTokenConfig {
public String toString() {
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", activityTimeout=" + activityTimeout
+ ", isShare=" + isShare + ", isReadBody=" + isReadBody + ", isReadHead=" + isReadHead
+ ", isReadCookie=" + isReadCookie + ", tokenStyle=" + tokenStyle + ", isV=" + isV + "]";
+ ", isReadCookie=" + isReadCookie + ", tokenStyle=" + tokenStyle + ", isV=" + isV
+ ", dataRefreshPeriod=" + dataRefreshPeriod + "]";
}

View File

@ -1,9 +1,15 @@
package cn.dev33.satoken.dao;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaTaskUtil;
import cn.dev33.satoken.util.SaTaskUtil.FunctionRunClass;
/**
* sa-token持久层默认的实现类 , 基于内存Map
@ -11,17 +17,27 @@ import cn.dev33.satoken.session.SaSession;
*
*/
public class SaTokenDaoDefaultImpl implements SaTokenDao {
/**
* 所有数据集合
*/
public Map<String, Object> dataMap = new HashMap<String, Object>();
public Map<String, Object> dataMap = new ConcurrentHashMap<String, Object>();
/**
* 过期时间集合 (单位: 毫秒) , 记录所有key的到期时间 [注意不是剩余存活时间]
*/
public Map<String, Long> expireMap = new HashMap<String, Long>();
public Map<String, Long> expireMap = new ConcurrentHashMap<String, Long>();
/**
* 构造函数
*/
public SaTokenDaoDefaultImpl() {
initRefreshTimer();
}
// ------------------------ String 读写操作
@Override
public String getValue(String key) {
@ -53,7 +69,9 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
public long getTimeout(String key) {
return getKeyTimeout(key);
}
// ------------------------ Session 读写操作
@Override
public SaSession getSession(String sessionId) {
@ -87,8 +105,7 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
// ---------------------
// ------------------------ Session 读写操作
/**
* 如果指定key已经过期则立即清除它
@ -131,8 +148,51 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
// --------------------- 定时清理过期数据
/**
* 定时任务对象
*/
public Timer refreshTimer;
/**
* 清理所有已经过期的key
*/
public void refreshDataMap() {
Iterator<String> keys = expireMap.keySet().iterator();
while (keys.hasNext()) {
clearKeyByTimeout(keys.next());
}
}
/**
* 初始化定时任务
*/
public void initRefreshTimer() {
// 如果已经被初始化过了, 则停止它
if(this.refreshTimer != null) {
this.endRefreshTimer();
}
// 开始新的定时任务
if(SaTokenManager.getConfig().getDataRefreshPeriod() < 0) {
return;
}
int period = SaTokenManager.getConfig().getDataRefreshPeriod() * 1000;
this.refreshTimer = SaTaskUtil.setInterval(new FunctionRunClass() {
@Override
public void run() {
refreshDataMap();
}
}, period, period);
}
/**
* 结束定时任务
*/
public void endRefreshTimer() {
this.refreshTimer.cancel();
}

View File

@ -0,0 +1,57 @@
package cn.dev33.satoken.util;
import java.util.Timer;
import java.util.TimerTask;
/**
* 任务调度Util
* @author kong
*
*/
public class SaTaskUtil {
/**
* 延时指定毫秒执行一个函数
* @param fc 要执行的函数
* @param delay 延时的毫秒数
* @return timer任务对象
*/
public static Timer setTimeout(FunctionRunClass fc, int delay) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
fc.run();
timer.cancel();
}
}, delay);
return timer;
}
/**
* 延时delay毫秒每隔period毫秒执行一个函数
* @param fc 要执行的函数
* @param delay 延时的毫秒数
* @param period 每隔多少毫秒执行一次
* @return timer任务对象
*/
public static Timer setInterval(FunctionRunClass fc, int delay, int period) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
fc.run();
}
}, delay, period);
return timer;
}
/**
* 封装一个内部类便于操作
* @author kong
*/
public static interface FunctionRunClass{
public void run();
}
}

View File

@ -33,11 +33,11 @@
</dependency>
<!-- sa-token 整合 redis -->
<dependency>
<!-- <dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>1.7.0</version>
</dependency>
</dependency> -->
<!-- @ConfigurationProperties -->
<dependency>

View File

@ -11,7 +11,6 @@ public class SaTokenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("\n启动成功sa-token配置如下" + SaTokenManager.getConfig());
System.out.println(SaTokenManager.getSaTokenDao());
}
}

View File

@ -77,4 +77,5 @@ spring:
| isReadHead | Boolean | true | 是否尝试从header里读取token |
| isReadCookie | Boolean | true | 是否尝试从cookie里读取token |
| tokenStyle | String | uuid | token风格, [参考花式token](/use/token-style) |
| dataRefreshPeriod | int | 30 | 默认dao层实现类中每次清理过期数据间隔的时间 (单位: 秒) 默认值30秒设置为-1代表不启动定时清理 |
| isV | Boolean | true | 是否在初始化配置时打印版本字符画 |