From 44ecbe784590ac7045e317a9c1f829ea05f97478 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?=
<15040126243@163.com>
Date: Tue, 3 Jan 2023 13:20:20 +0800
Subject: [PATCH 1/3] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=20=E9=80=82?=
=?UTF-8?q?=E9=85=8D=20redisson=20=E5=AE=A2=E6=88=B7=E7=AB=AF=20jackson=20?=
=?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=20=E6=8F=92=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sa-token-dependencies/pom.xml | 15 +
sa-token-plugin/pom.xml | 1 +
.../sa-token-dao-redisson-jackson/.gitignore | 13 +
.../sa-token-dao-redisson-jackson/pom.xml | 48 +++
.../dao/SaSessionForJacksonCustomized.java | 32 ++
.../dao/SaTokenDaoRedissonJackson.java | 283 ++++++++++++++++++
.../main/resources/META-INF/spring.factories | 1 +
7 files changed, 393 insertions(+)
create mode 100644 sa-token-plugin/sa-token-dao-redisson-jackson/.gitignore
create mode 100644 sa-token-plugin/sa-token-dao-redisson-jackson/pom.xml
create mode 100644 sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaSessionForJacksonCustomized.java
create mode 100644 sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedissonJackson.java
create mode 100644 sa-token-plugin/sa-token-dao-redisson-jackson/src/main/resources/META-INF/spring.factories
diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml
index f172bbd8..ae1dbbdf 100644
--- a/sa-token-dependencies/pom.xml
+++ b/sa-token-dependencies/pom.xml
@@ -32,6 +32,7 @@
0.9.1
1.2.83
2.0.15
+ 3.19.0
@@ -120,6 +121,13 @@
spring-boot-starter-data-redis
${springboot.version}
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
@@ -183,6 +191,13 @@
spring-boot-starter-aop
${springboot.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+ ${springboot.version}
+
diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml
index 71e22215..80213083 100644
--- a/sa-token-plugin/pom.xml
+++ b/sa-token-plugin/pom.xml
@@ -22,6 +22,7 @@
sa-token-dao-redis-jackson
sa-token-dao-redis-fastjson
sa-token-dao-redis-fastjson2
+ sa-token-dao-redisson-jackson
sa-token-dao-redisx
sa-token-alone-redis
sa-token-dialect-thymeleaf
diff --git a/sa-token-plugin/sa-token-dao-redisson-jackson/.gitignore b/sa-token-plugin/sa-token-dao-redisson-jackson/.gitignore
new file mode 100644
index 00000000..8122f47c
--- /dev/null
+++ b/sa-token-plugin/sa-token-dao-redisson-jackson/.gitignore
@@ -0,0 +1,13 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
+.iml
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-dao-redisson-jackson/pom.xml b/sa-token-plugin/sa-token-dao-redisson-jackson/pom.xml
new file mode 100644
index 00000000..568c020e
--- /dev/null
+++ b/sa-token-plugin/sa-token-dao-redisson-jackson/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-plugin
+ ${revision}
+ ../pom.xml
+
+ jar
+
+ sa-token-dao-redisson-jackson
+ sa-token-dao-redisson-jackson
+ sa-token integrate redisson (to jackson)
+
+
+
+
+ cn.dev33
+ sa-token-core
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ true
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ true
+
+
+
+
+
+
+
diff --git a/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaSessionForJacksonCustomized.java b/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaSessionForJacksonCustomized.java
new file mode 100644
index 00000000..d4505508
--- /dev/null
+++ b/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaSessionForJacksonCustomized.java
@@ -0,0 +1,32 @@
+package cn.dev33.satoken.dao;
+
+import cn.dev33.satoken.session.SaSession;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Jackson定制版SaSession,忽略 timeout 等属性的序列化
+ *
+ * @author kong
+ *
+ */
+@JsonIgnoreProperties({"timeout"})
+public class SaSessionForJacksonCustomized extends SaSession {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7600983549653130681L;
+
+ public SaSessionForJacksonCustomized() {
+ super();
+ }
+
+ /**
+ * 构建一个Session对象
+ * @param id Session的id
+ */
+ public SaSessionForJacksonCustomized(String id) {
+ super(id);
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedissonJackson.java b/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedissonJackson.java
new file mode 100644
index 00000000..b0ea9d45
--- /dev/null
+++ b/sa-token-plugin/sa-token-dao-redisson-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedissonJackson.java
@@ -0,0 +1,283 @@
+package cn.dev33.satoken.dao;
+
+import cn.dev33.satoken.strategy.SaStrategy;
+import cn.dev33.satoken.util.SaFoxUtil;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import org.redisson.api.RBatch;
+import org.redisson.api.RBucket;
+import org.redisson.api.RBucketAsync;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Field;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Sa-Token 持久层实现 [Redisson客户端、Redis存储、Jackson序列化]
+ *
+ * @author 疯狂的狮子Li
+ *
+ */
+@Component
+public class SaTokenDaoRedissonJackson implements SaTokenDao {
+
+ public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ public static final String DATE_PATTERN = "yyyy-MM-dd";
+ public static final String TIME_PATTERN = "HH:mm:ss";
+ public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
+ public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);
+ public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_PATTERN);
+
+ /**
+ * ObjectMapper对象 (以public作用域暴露出此对象,方便开发者二次更改配置)
+ */
+ public ObjectMapper objectMapper;
+
+ /**
+ * redisson 客户端
+ */
+ public RedissonClient redissonClient;
+
+ /**
+ * 标记:是否已初始化成功
+ */
+ public boolean isInit;
+
+ @Autowired
+ public void init(RedissonClient redissonClient) {
+ // 不重复初始化
+ if(this.isInit) {
+ return;
+ }
+
+ // 指定相应的序列化方案
+ GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
+ // 通过反射获取Mapper对象, 增加一些配置, 增强兼容性
+ try {
+ Field field = GenericJackson2JsonRedisSerializer.class.getDeclaredField("mapper");
+ field.setAccessible(true);
+ ObjectMapper objectMapper = (ObjectMapper) field.get(valueSerializer);
+ this.objectMapper = objectMapper;
+ // 配置[忽略未知字段]
+ this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ // 配置[时间类型转换]
+ JavaTimeModule timeModule = new JavaTimeModule();
+ // LocalDateTime序列化与反序列化
+ timeModule.addSerializer(new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
+ timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER));
+ // LocalDate序列化与反序列化
+ timeModule.addSerializer(new LocalDateSerializer(DATE_FORMATTER));
+ timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DATE_FORMATTER));
+ // LocalTime序列化与反序列化
+ timeModule.addSerializer(new LocalTimeSerializer(TIME_FORMATTER));
+ timeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(TIME_FORMATTER));
+ this.objectMapper.registerModule(timeModule);
+ // 重写 SaSession 生成策略
+ SaStrategy.me.createSession = (sessionId) -> new SaSessionForJacksonCustomized(sessionId);
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+
+ // 开始初始化相关组件
+ redissonClient.getConfig().setCodec(new JsonJacksonCodec(objectMapper));
+ this.redissonClient = redissonClient;
+ this.isInit = true;
+ }
+
+
+ /**
+ * 获取Value,如无返空
+ */
+ @Override
+ public String get(String key) {
+ RBucket rBucket = redissonClient.getBucket(key);
+ return rBucket.get();
+ }
+
+ /**
+ * 写入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) {
+ RBucket bucket = redissonClient.getBucket(key);
+ bucket.set(value);
+ } else {
+ RBatch batch = redissonClient.createBatch();
+ RBucketAsync bucket = batch.getBucket(key);
+ bucket.setAsync(value);
+ bucket.expireAsync(Duration.ofSeconds(timeout));
+ batch.execute();
+ }
+ }
+
+ /**
+ * 修修改指定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) {
+ redissonClient.getBucket(key).delete();
+ }
+
+ /**
+ * 获取Value的剩余存活时间 (单位: 秒)
+ */
+ @Override
+ public long getTimeout(String key) {
+ RBucket rBucket = redissonClient.getBucket(key);
+ long timeout = rBucket.remainTimeToLive();
+ return timeout < 0 ? timeout : timeout / 1000;
+ }
+
+ /**
+ * 修改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;
+ }
+ RBucket rBucket = redissonClient.getBucket(key);
+ rBucket.expire(Duration.ofSeconds(timeout));
+ }
+
+
+
+ /**
+ * 获取Object,如无返空
+ */
+ @Override
+ public Object getObject(String key) {
+ RBucket