From 34f63449f78bba9e397d52f8ecb4d4ff9a242e75 Mon Sep 17 00:00:00 2001 From: noear Date: Sun, 15 Jan 2023 09:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=20sa-token-dao-redisx=20?= =?UTF-8?q?=E9=80=82=E9=85=8D=EF=BC=88=E6=8F=90=E4=BE=9B=20base64,=20json?= =?UTF-8?q?=20=E4=B8=A4=E7=A7=8D=E5=BA=8F=E5=88=97=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E6=A1=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sa-token-dependencies/pom.xml | 8 + sa-token-plugin/sa-token-dao-redisx/pom.xml | 6 + .../dev33/satoken/dao/SaSessionForJson.java | 73 +++++++ .../dev33/satoken/dao/SaTokenDaoOfRedis.java | 176 +--------------- .../satoken/dao/SaTokenDaoOfRedisBase64.java | 185 ++++++++++++++++ .../satoken/dao/SaTokenDaoOfRedisJson.java | 198 ++++++++++++++++++ 6 files changed, 478 insertions(+), 168 deletions(-) create mode 100644 sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaSessionForJson.java create mode 100644 sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisBase64.java create mode 100644 sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisJson.java diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml index 5f6b3f09..47955d76 100644 --- a/sa-token-dependencies/pom.xml +++ b/sa-token-dependencies/pom.xml @@ -25,6 +25,7 @@ 3.0.9.RELEASE 1.12.2 1.4.5 + 3.2.50 4.9.17 3.14.4 2.5.0 @@ -96,6 +97,13 @@ solon ${solon.version} + + + + org.noear + snack3 + ${noear-snack3.version} + diff --git a/sa-token-plugin/sa-token-dao-redisx/pom.xml b/sa-token-plugin/sa-token-dao-redisx/pom.xml index 91a50216..e7042391 100644 --- a/sa-token-plugin/sa-token-dao-redisx/pom.xml +++ b/sa-token-plugin/sa-token-dao-redisx/pom.xml @@ -28,6 +28,12 @@ redisx + + org.noear + snack3 + provided + + org.noear solon-test diff --git a/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaSessionForJson.java b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaSessionForJson.java new file mode 100644 index 00000000..b26a72ae --- /dev/null +++ b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaSessionForJson.java @@ -0,0 +1,73 @@ +package cn.dev33.satoken.dao; + +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.util.SaFoxUtil; +import org.noear.snack.ONode; + +/** + * Snack3 定制版 SaSession,重写类型转换API + * + * @author noear + * @since 1.12 + */ +public class SaSessionForJson extends SaSession { + + private static final long serialVersionUID = -7600983549653130681L; + + public SaSessionForJson() { + super(); + } + + /** + * 构建一个 SaSession 对象 + * @param id Session 的 id + */ + public SaSessionForJson(String id) { + super(id); + } + + /** + * 取值 (指定转换类型) + * @param 泛型 + * @param key key + * @param cs 指定转换类型 + * @return 值 + */ + @Override + public T getModel(String key, Class cs) { + if(SaFoxUtil.isBasicType(cs)) { + return SaFoxUtil.getValueByType(get(key), cs); + } + return ONode.deserialize(getString(key), cs); + } + + /** + * 取值 (指定转换类型, 并指定值为Null时返回的默认值) + * @param 泛型 + * @param key key + * @param cs 指定转换类型 + * @param defaultValue 值为Null时返回的默认值 + * @return 值 + */ + @Override + @SuppressWarnings("unchecked") + public T getModel(String key, Class cs, Object defaultValue) { + Object value = get(key); + if(valueIsNull(value)) { + return (T)defaultValue; + } + if(SaFoxUtil.isBasicType(cs)) { + return SaFoxUtil.getValueByType(get(key), cs); + } + return ONode.deserialize(getString(key), cs); + } + + /** + * 忽略 timeout 字段的序列化 + */ + @Override + public long getTimeout() { + return super.getTimeout(); + } + +} diff --git a/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedis.java b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedis.java index d499570a..d6be13e3 100644 --- a/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedis.java +++ b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedis.java @@ -1,185 +1,25 @@ package cn.dev33.satoken.dao; -import cn.dev33.satoken.util.SaFoxUtil; import org.noear.redisx.RedisClient; -import org.noear.redisx.plus.RedisBucket; +import org.noear.solon.annotation.Note; -import java.util.ArrayList; -import java.util.List; import java.util.Properties; -import java.util.Set; /** - * SaTokenDao 的 redis 适配(相对于之前的 redis 适配;主要去除去 Spring 的依赖) + * SaTokenDao 的 redis 适配 * * @author noear - * @since 2022-03-30 + * @since 1.6 */ -public class SaTokenDaoOfRedis implements SaTokenDao { - private final RedisBucket redisBucket; +@Note("更名为:SaTokenDaoOfRedisBase64") +@Deprecated +public class SaTokenDaoOfRedis extends SaTokenDaoOfRedisBase64 { public SaTokenDaoOfRedis(Properties props) { - this(new RedisClient(props)); + super(props); } public SaTokenDaoOfRedis(RedisClient redisClient) { - redisBucket = redisClient.getBucket(); - } - - - /** - * 获取Value,如无返空 - */ - @Override - public String get(String key) { - return redisBucket.get(key); - } - - /** - * 写入Value,并设定存活时间 (单位: 秒) - */ - @Override - public void set(String key, String value, long timeout) { - if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { - return; - } - // 判断是否为永不过期 - if (timeout == SaTokenDao.NEVER_EXPIRE) { - redisBucket.store(key, value, (int) SaTokenDao.NEVER_EXPIRE); - } else { - redisBucket.store(key, value, (int) timeout); - } - } - - /** - * 修改指定key-value键值对 (过期时间不变) - */ - @Override - public void update(String key, String value) { - long expire = getTimeout(key); - // -2 = 无此键 - if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { - return; - } - this.set(key, value, expire); - } - - /** - * 删除Value - */ - @Override - public void delete(String key) { - redisBucket.remove(key); - } - - /** - * 获取Value的剩余存活时间 (单位: 秒) - */ - @Override - public long getTimeout(String key) { - return redisBucket.ttl(key); - } - - /** - * 修改Value的剩余存活时间 (单位: 秒) - */ - @Override - public void updateTimeout(String key, long timeout) { - // 判断是否想要设置为永久 - if (timeout == SaTokenDao.NEVER_EXPIRE) { - long expire = getTimeout(key); - if (expire == SaTokenDao.NEVER_EXPIRE) { - // 如果其已经被设置为永久,则不作任何处理 - } else { - // 如果尚未被设置为永久,那么再次set一次 - this.set(key, this.get(key), timeout); - } - return; - } - redisBucket.delay(key, (int) timeout); - } - - - /** - * 获取Object,如无返空 - */ - @Override - public Object getObject(String key) { - return redisBucket.getAndDeserialize(key); - } - - /** - * 写入Object,并设定存活时间 (单位: 秒) - */ - @Override - public void setObject(String key, Object object, long timeout) { - if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { - return; - } - // 判断是否为永不过期 - if (timeout == SaTokenDao.NEVER_EXPIRE) { - redisBucket.storeAndSerialize(key, object); - } else { - redisBucket.storeAndSerialize(key, object, (int) timeout); - } - } - - /** - * 更新Object (过期时间不变) - */ - @Override - public void updateObject(String key, Object object) { - long expire = getObjectTimeout(key); - // -2 = 无此键 - if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { - return; - } - this.setObject(key, object, expire); - } - - /** - * 删除Object - */ - @Override - public void deleteObject(String key) { - redisBucket.remove(key); - } - - /** - * 获取Object的剩余存活时间 (单位: 秒) - */ - @Override - public long getObjectTimeout(String key) { - return redisBucket.ttl(key); - } - - /** - * 修改Object的剩余存活时间 (单位: 秒) - */ - @Override - public void updateObjectTimeout(String key, long timeout) { - // 判断是否想要设置为永久 - if (timeout == SaTokenDao.NEVER_EXPIRE) { - long expire = getObjectTimeout(key); - if (expire == SaTokenDao.NEVER_EXPIRE) { - // 如果其已经被设置为永久,则不作任何处理 - } else { - // 如果尚未被设置为永久,那么再次set一次 - this.setObject(key, this.getObject(key), timeout); - } - return; - } - redisBucket.delay(key, (int) timeout); - } - - - /** - * 搜索数据 - */ - @Override - public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { - Set keys = redisBucket.keys(prefix + "*" + keyword + "*"); - List list = new ArrayList(keys); - return SaFoxUtil.searchList(list, start, size, sortType); + super(redisClient); } } \ No newline at end of file diff --git a/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisBase64.java b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisBase64.java new file mode 100644 index 00000000..2c95e5bd --- /dev/null +++ b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisBase64.java @@ -0,0 +1,185 @@ +package cn.dev33.satoken.dao; + +import cn.dev33.satoken.util.SaFoxUtil; +import org.noear.redisx.RedisClient; +import org.noear.redisx.plus.RedisBucket; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +/** + * SaTokenDao 的 redis 适配(可以完全精准还原所有序列化类型) + * + * @author noear + * @since 1.6 + */ +public class SaTokenDaoOfRedisBase64 implements SaTokenDao { + private final RedisBucket redisBucket; + + public SaTokenDaoOfRedisBase64(Properties props) { + this(new RedisClient(props)); + } + + public SaTokenDaoOfRedisBase64(RedisClient redisClient) { + redisBucket = redisClient.getBucket(); + } + + + /** + * 获取Value,如无返空 + */ + @Override + public String get(String key) { + return redisBucket.get(key); + } + + /** + * 写入Value,并设定存活时间 (单位: 秒) + */ + @Override + public void set(String key, String value, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + redisBucket.store(key, value, (int) SaTokenDao.NEVER_EXPIRE); + } else { + redisBucket.store(key, value, (int) timeout); + } + } + + /** + * 修改指定key-value键值对 (过期时间不变) + */ + @Override + public void update(String key, String value) { + long expire = getTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.set(key, value, expire); + } + + /** + * 删除Value + */ + @Override + public void delete(String key) { + redisBucket.remove(key); + } + + /** + * 获取Value的剩余存活时间 (单位: 秒) + */ + @Override + public long getTimeout(String key) { + return redisBucket.ttl(key); + } + + /** + * 修改Value的剩余存活时间 (单位: 秒) + */ + @Override + public void updateTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.set(key, this.get(key), timeout); + } + return; + } + redisBucket.delay(key, (int) timeout); + } + + + /** + * 获取Object,如无返空 + */ + @Override + public Object getObject(String key) { + return redisBucket.getAndDeserialize(key); + } + + /** + * 写入Object,并设定存活时间 (单位: 秒) + */ + @Override + public void setObject(String key, Object object, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + redisBucket.storeAndSerialize(key, object); + } else { + redisBucket.storeAndSerialize(key, object, (int) timeout); + } + } + + /** + * 更新Object (过期时间不变) + */ + @Override + public void updateObject(String key, Object object) { + long expire = getObjectTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.setObject(key, object, expire); + } + + /** + * 删除Object + */ + @Override + public void deleteObject(String key) { + redisBucket.remove(key); + } + + /** + * 获取Object的剩余存活时间 (单位: 秒) + */ + @Override + public long getObjectTimeout(String key) { + return redisBucket.ttl(key); + } + + /** + * 修改Object的剩余存活时间 (单位: 秒) + */ + @Override + public void updateObjectTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getObjectTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.setObject(key, this.getObject(key), timeout); + } + return; + } + redisBucket.delay(key, (int) timeout); + } + + + /** + * 搜索数据 + */ + @Override + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { + Set keys = redisBucket.keys(prefix + "*" + keyword + "*"); + List list = new ArrayList(keys); + return SaFoxUtil.searchList(list, start, size, sortType); + } +} \ No newline at end of file diff --git a/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisJson.java b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisJson.java new file mode 100644 index 00000000..98ae43a1 --- /dev/null +++ b/sa-token-plugin/sa-token-dao-redisx/src/main/java/cn/dev33/satoken/dao/SaTokenDaoOfRedisJson.java @@ -0,0 +1,198 @@ +package cn.dev33.satoken.dao; + +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.strategy.SaStrategy; +import cn.dev33.satoken.util.SaFoxUtil; +import org.noear.redisx.RedisClient; +import org.noear.redisx.plus.RedisBucket; +import org.noear.snack.ONode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +/** + * SaTokenDao 的 redis 适配(基于json序列化,不能完全精准还原所有类型) + * + * @author noear + * @since 1.6 + */ +public class SaTokenDaoOfRedisJson implements SaTokenDao { + private final RedisBucket redisBucket; + + public SaTokenDaoOfRedisJson(Properties props) { + this(new RedisClient(props)); + } + + public SaTokenDaoOfRedisJson(RedisClient redisClient) { + redisBucket = redisClient.getBucket(); + + // 重写 SaSession 生成策略 + SaStrategy.me.createSession = (sessionId) -> new SaSessionForJson(sessionId); + + } + + @Override + public SaSession getSession(String sessionId) { + Object obj = getObject(sessionId); + if (obj == null) { + return null; + } + return ONode.deserialize(obj.toString(), SaSessionForJson.class); + } + + + /** + * 获取Value,如无返空 + */ + @Override + public String get(String key) { + return redisBucket.get(key); + } + + /** + * 写入Value,并设定存活时间 (单位: 秒) + */ + @Override + public void set(String key, String value, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + redisBucket.store(key, value, (int) SaTokenDao.NEVER_EXPIRE); + } else { + redisBucket.store(key, value, (int) timeout); + } + } + + /** + * 修改指定key-value键值对 (过期时间不变) + */ + @Override + public void update(String key, String value) { + long expire = getTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.set(key, value, expire); + } + + /** + * 删除Value + */ + @Override + public void delete(String key) { + redisBucket.remove(key); + } + + /** + * 获取Value的剩余存活时间 (单位: 秒) + */ + @Override + public long getTimeout(String key) { + return redisBucket.ttl(key); + } + + /** + * 修改Value的剩余存活时间 (单位: 秒) + */ + @Override + public void updateTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.set(key, this.get(key), timeout); + } + return; + } + redisBucket.delay(key, (int) timeout); + } + + + /** + * 获取Object,如无返空 + */ + @Override + public Object getObject(String key) { + return get(key); + } + + /** + * 写入Object,并设定存活时间 (单位: 秒) + */ + @Override + public void setObject(String key, Object object, long timeout) { + if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + + String value = ONode.serialize(object); + set(key, value, timeout); + } + + /** + * 更新Object (过期时间不变) + */ + @Override + public void updateObject(String key, Object object) { + long expire = getObjectTimeout(key); + // -2 = 无此键 + if (expire == SaTokenDao.NOT_VALUE_EXPIRE) { + return; + } + this.setObject(key, object, expire); + } + + /** + * 删除Object + */ + @Override + public void deleteObject(String key) { + redisBucket.remove(key); + } + + /** + * 获取Object的剩余存活时间 (单位: 秒) + */ + @Override + public long getObjectTimeout(String key) { + return redisBucket.ttl(key); + } + + /** + * 修改Object的剩余存活时间 (单位: 秒) + */ + @Override + public void updateObjectTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == SaTokenDao.NEVER_EXPIRE) { + long expire = getObjectTimeout(key); + if (expire == SaTokenDao.NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.setObject(key, this.getObject(key), timeout); + } + return; + } + redisBucket.delay(key, (int) timeout); + } + + + /** + * 搜索数据 + */ + @Override + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { + Set keys = redisBucket.keys(prefix + "*" + keyword + "*"); + List list = new ArrayList(keys); + return SaFoxUtil.searchList(list, start, size, sortType); + } +} \ No newline at end of file