修复jFinal,jboot插件Redis缓存方法与通用方法不一致的问题

增加缓存序列化方法
This commit is contained in:
赵锋 2021-12-17 11:15:04 +08:00
parent 40a6da10fe
commit 4784cbd103
8 changed files with 682 additions and 29 deletions

View File

@ -0,0 +1,70 @@
package cn.dev33.satoken.jboot;
import com.jfinal.kit.LogKit;
import com.jfinal.plugin.redis.serializer.ISerializer;
import com.jfinal.plugin.redis.serializer.JdkSerializer;
import redis.clients.jedis.util.SafeEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SaJdkSerializer implements ISerializer {
public static final ISerializer me = new JdkSerializer();
public byte[] keyToBytes(String key) {
return SafeEncoder.encode(key);
}
public String keyFromBytes(byte[] bytes) {
return SafeEncoder.encode(bytes);
}
public byte[] fieldToBytes(Object field) {
return valueToBytes(field);
}
public Object fieldFromBytes(byte[] bytes) {
return valueFromBytes(bytes);
}
public byte[] valueToBytes(Object value) {
ObjectOutputStream objectOut = null;
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(1024);
objectOut = new ObjectOutputStream(bytesOut);
objectOut.writeObject(value);
objectOut.flush();
return bytesOut.toByteArray();
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
if(objectOut != null)
try {objectOut.close();} catch (Exception e) {
LogKit.error(e.getMessage(), e);}
}
}
public Object valueFromBytes(byte[] bytes) {
if(bytes == null || bytes.length == 0)
return null;
ObjectInputStream objectInput = null;
try {
ByteArrayInputStream bytesInput = new ByteArrayInputStream(bytes);
objectInput = new ObjectInputStream(bytesInput);
return objectInput.readObject();
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
if (objectInput != null)
try {objectInput.close();} catch (Exception e) {LogKit.error(e.getMessage(), e);}
}
}
}

View File

@ -0,0 +1,460 @@
package cn.dev33.satoken.jboot;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.util.SaFoxUtil;
import com.jfinal.log.Log;
import io.jboot.Jboot;
import io.jboot.components.serializer.JbootSerializer;
import io.jboot.components.serializer.JbootSerializerManager;
import io.jboot.exception.JbootIllegalConfigException;
import io.jboot.support.redis.JbootRedisBase;
import io.jboot.utils.StrUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SaJedisImpl {
private final JbootSerializer serializer;
protected JedisPool jedisPool;
private static final Log LOG = Log.getLog(SaJedisImpl.class);
private final SaRedisConfig config;
public SaJedisImpl(SaRedisConfig config) {
if (config == null || StrUtil.isBlank(config.getSerializer())) {
serializer = Jboot.getSerializer();
} else {
serializer = JbootSerializerManager.me().getSerializer(config.getSerializer());
}
this.config = config;
String host = config.getHost();
Integer port = config.getPort();
Integer timeout = config.getTimeout();
String password = config.getPassword();
Integer database = config.getSadb();
String clientName = config.getClientName();
if (host.contains(":")) {
port = Integer.valueOf(host.split(":")[1]);
}
JedisPoolConfig poolConfig = new JedisPoolConfig();
if (StrUtil.isNotBlank(config.getTestWhileIdle())) {
poolConfig.setTestWhileIdle(config.getTestWhileIdle());
}
if (StrUtil.isNotBlank(config.getTestOnBorrow())) {
poolConfig.setTestOnBorrow(config.getTestOnBorrow());
}
if (StrUtil.isNotBlank(config.getTestOnCreate())) {
poolConfig.setTestOnCreate(config.getTestOnCreate());
}
if (StrUtil.isNotBlank(config.getTestOnReturn())) {
poolConfig.setTestOnReturn(config.getTestOnReturn());
}
if (StrUtil.isNotBlank(config.getMinEvictableIdleTimeMillis())) {
poolConfig.setMinEvictableIdleTime(Duration.ofMillis(config.getMinEvictableIdleTimeMillis()));
}
if (StrUtil.isNotBlank(config.getTimeBetweenEvictionRunsMillis())) {
poolConfig.setSoftMinEvictableIdleTime(Duration.ofMillis(config.getTimeBetweenEvictionRunsMillis()));
}
if (StrUtil.isNotBlank(config.getNumTestsPerEvictionRun())) {
poolConfig.setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
}
if (StrUtil.isNotBlank(config.getMaxTotal())) {
poolConfig.setMaxTotal(config.getMaxTotal());
}
if (StrUtil.isNotBlank(config.getMaxIdle())) {
poolConfig.setMaxIdle(config.getMaxIdle());
}
if (StrUtil.isNotBlank(config.getMinIdle())) {
poolConfig.setMinIdle(config.getMinIdle());
}
if (StrUtil.isNotBlank(config.getMaxWaitMillis())) {
poolConfig.setMaxWaitMillis(config.getMaxWaitMillis());
}
this.jedisPool = new JedisPool(poolConfig, host, port, timeout, timeout, password, database, clientName);
}
/**
* 获取Value如无返空
* @param key
* @return
*/
public String get(String key){
Jedis jedis = getJedis();
try{
return jedis.get(key);
}finally {
returnResource(jedis);
}
}
/**
* 写入Value
* @param key
* @param value
*/
public void set(String key, String value) {
Jedis jedis = getJedis();
try{
jedis.set(key, value);
}finally {
returnResource(jedis);
}
}
/**
* 写入Value并设定存活时间 (单位: )
* @param key
* @param value
* @param timeout
*/
public void setex(String key, String value, long timeout){
Jedis jedis = getJedis();
try{
jedis.setex(key,timeout,value);
}finally {
returnResource(jedis);
}
}
/**
* 删除Value
* @param key
*/
public void del(String key) {
Jedis jedis = getJedis();
try{
jedis.del(key);
}finally {
returnResource(jedis);
}
}
/**
* 获取Value的剩余存活时间 (单位: )
* @param key
* @return
*/
public long ttl(String key) {
Jedis jedis = getJedis();
try{
return jedis.ttl(key);
}finally {
returnResource(jedis);
}
}
public void expire(String key,long timeout){
Jedis jedis = getJedis();
try {
jedis.expire(key,timeout);
} finally {
returnResource(jedis);
}
}
/**
* 获取Object如无返空
* @param key
* @return
*/
public Object getObject(String key) {
Jedis jedis = getJedis();
try {
return valueFromBytes(jedis.get(keyToBytes(key)));
} finally {
returnResource(jedis);
}
}
/**
* 写入Object
* @param key
* @param value
*/
public void setObject(Object key, Object value) {
Jedis jedis = getJedis();
try {
jedis.set(keyToBytes(key), valueToBytes(value));
} finally {
returnResource(jedis);
}
}
/**
* 写入Object并设定存活时间 (单位: )
* @param key
* @param object
* @param timeout
*/
public void setexObject(String key, Object object,long timeout) {
Jedis jedis = getJedis();
try {
jedis.setex(keyToBytes(key),timeout, valueToBytes(object));
} finally {
returnResource(jedis);
}
}
/**
* 删除Object
* @param key
*/
public void deleteObject(String key) {
Jedis jedis = getJedis();
try {
jedis.del(keyToBytes(key));
} finally {
returnResource(jedis);
}
}
public long getObjectTimeout(String key) {
Jedis jedis = getJedis();
try {
return getJedis().ttl(keyToBytes(key));
} finally {
returnResource(jedis);
}
}
/**
* 修改Object的剩余存活时间 (单位: )
* @param key
* @param timeout
*/
public void expireObject(String key, long timeout) {
Jedis jedis = getJedis();
try {
jedis.expire(keyToBytes(key), timeout);
}
finally {
returnResource(jedis);
}
}
/**
* 查找所有符合给定模式 pattern key
* KEYS * 匹配数据库中所有 key
* KEYS h?llo 匹配 hello hallo hxllo
* KEYS h*llo 匹配 hllo heeeeello
* KEYS h[ae]llo 匹配 hello hallo 但不匹配 hillo
* 特殊符号用 \ 隔开
*/
public Set<String> keys(String pattern) {
Jedis jedis = getJedis();
try {
return jedis.keys(pattern);
} finally {
returnResource(jedis);
}
}
/**
* 将哈希表 key 中的域 field 的值设为 value
* 如果 key 不存在一个新的哈希表被创建并进行 HSET 操作
* 如果域 field 已经存在于哈希表中旧值将被覆盖
*/
public Long hset(String key, String field, String value) {
Jedis jedis = getJedis();
try {
return jedis.hset(key, field, value);
} finally {
returnResource(jedis);
}
}
/**
* 同时将多个 field-value (-)对设置到哈希表 key
* 此命令会覆盖哈希表中已存在的域
* 如果 key 不存在一个空哈希表被创建并执行 HMSET 操作
*/
public String hmset(String key, Map<String, String> hash) {
Jedis jedis = getJedis();
try {
return jedis.hmset(key,hash);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 中给定域 field 的值
* @param key
* @param field
* @return
*/
public String hget(String key,String field){
Jedis jedis = getJedis();
try {
return jedis.hget(key,field);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 一个或多个给定域的值
* 如果给定的域不存在于哈希表那么返回一个 nil
* 因为不存在的 key 被当作一个空哈希表来处理所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表
*/
public List<String> hmget(String key, String... fields) {
Jedis jedis = getJedis();
try {
return jedis.hmget(key,fields);
} finally {
returnResource(jedis);
}
}
/**
* 删除哈希表 key 中的一个或多个指定域不存在的域将被忽略
* @param key
* @param fields
* @return
*/
public Long hdel(String key, String... fields) {
Jedis jedis = getJedis();
try {
return jedis.hdel(key,fields);
} finally {
returnResource(jedis);
}
}
/**
* 查看哈希表 key 给定域 field 是否存在
* @param key
* @param field
* @return
*/
public boolean hexists(String key, String field){
Jedis jedis = getJedis();
try {
return jedis.hexists(key,field);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 所有的域和值
* 在返回值里紧跟每个域名(field name)之后是域的值(value)所以返回值的长度是哈希表大小的两倍
*/
public Map<String, String> hgetAll(String key) {
Jedis jedis = getJedis();
try {
return jedis.hgetAll(key);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 中所有域的值
* @param key
* @return
*/
public List<String> hvals(String key) {
Jedis jedis = getJedis();
try {
return jedis.hvals(key);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 中的所有域
* @param key
* @return
*/
public Set<String> hkeys(String key){
Jedis jedis = getJedis();
try {
return jedis.hkeys(key);
} finally {
returnResource(jedis);
}
}
/**
* 返回哈希表 key 中域的数量
* @param key
* @return
*/
public Long hlen(String key){
Jedis jedis = getJedis();
try {
return jedis.hlen(key);
} finally {
returnResource(jedis);
}
}
public Jedis getJedis() {
try {
return jedisPool.getResource();
} catch (JedisConnectionException e) {
throw new JbootIllegalConfigException("can not connect to redis host " + config.getHost() + ":" + config.getPort() + " ," +
" cause : " + e.toString(), e);
}
}
public void returnResource(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
public byte[] keyToBytes(Object key) {
return key.toString().getBytes();
}
public String bytesToKey(byte[] bytes) {
return new String(bytes);
}
public byte[] valueToBytes(Object value) {
return serializer.serialize(value);
}
public Object valueFromBytes(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
return serializer.deserialize(bytes);
}
/**
* 搜索数据
* @param prefix
* @param keyword
* @param start
* @param size
* @return
*/
public List<String> searchData(String prefix, String keyword, int start, int size) {
Set<String> keys = getJedis().keys(prefix + "*" + keyword + "*");
List<String> list = new ArrayList<String>(keys);
return SaFoxUtil.searchList(list, start, size);
}
}

View File

@ -0,0 +1,24 @@
package cn.dev33.satoken.jboot;
import io.jboot.app.config.annotation.ConfigModel;
import io.jboot.support.redis.JbootRedisConfig;
/**
* SA-Token redis缓存配置
*/
@ConfigModel(
prefix = "sa.redis"
)
public class SaRedisConfig extends JbootRedisConfig{
private Integer sadb = 1;
public Integer getSadb() {
return this.sadb;
}
public void setSadb(Integer sadb) {
this.sadb = sadb;
}
}

View File

@ -0,0 +1,38 @@
package cn.dev33.satoken.jboot;
import io.jboot.Jboot;
public class SaRedisManager {
private static SaRedisManager manager = new SaRedisManager();
private SaRedisManager() {
}
public static SaRedisManager me() {
return manager;
}
private SaJedisImpl redis;
public SaJedisImpl getRedis() {
if (redis == null) {
SaRedisConfig config = Jboot.config(SaRedisConfig.class);
redis = getRedis(config);
}
return redis;
}
public SaJedisImpl getRedis(SaRedisConfig config) {
if (config == null || !config.isConfigOk()) {
return null;
}
return getJedisClient(config);
}
private SaJedisImpl getJedisClient(SaRedisConfig config) {
return new SaJedisImpl(config);
}
}

View File

@ -3,10 +3,7 @@ package cn.dev33.satoken.jboot;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.util.SaFoxUtil;
import io.jboot.Jboot;
import io.jboot.components.cache.redis.JbootRedisCacheConfig;
import io.jboot.exception.JbootIllegalConfigException;
import io.jboot.support.redis.JbootRedis;
import io.jboot.support.redis.JbootRedisManager;
import java.util.ArrayList;
import java.util.List;
@ -14,23 +11,18 @@ import java.util.Set;
public class SaTokenDaoRedis implements SaTokenDao {
private final JbootRedis redis;
private SaJedisImpl redis;
/**
* 标记是否已初始化成功
*/
public boolean isInit;
public SaTokenDaoRedis(){
JbootRedisCacheConfig redisConfig = Jboot.config(JbootRedisCacheConfig.class);
SaRedisConfig redisConfig = Jboot.config(SaRedisConfig.class);
redisConfig.setSerializer("cn.dev33.satoken.jboot.SaJdkSerializer");
//优先使用 jboot.cache.redis 的配置
if (redisConfig.isConfigOk()) {
redis = JbootRedisManager.me().getRedis(redisConfig);
}
// jboot.cache.redis 配置不存在时
// 使用 jboot.redis 的配置
else {
redis = Jboot.getRedis();
redis = SaRedisManager.me().getRedis(redisConfig);
}
if (redis == null) {
@ -65,7 +57,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
if(timeout == SaTokenDao.NEVER_EXPIRE) {
redis.set(key, value);
}else{
redis.setex(key,Integer.parseInt(timeout+""),value);
redis.setex(key,value,timeout);
}
}
@ -121,7 +113,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
return;
}
redis.expire(key,Integer.parseInt(timeout+""));
redis.expire(key,timeout);
}
/**
@ -131,7 +123,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public Object getObject(String key) {
return redis.get(key);
return redis.getObject(key);
}
/**
@ -146,9 +138,9 @@ public class SaTokenDaoRedis implements SaTokenDao {
return;
}
if(timeout == SaTokenDao.NEVER_EXPIRE) {
redis.set(key, object);
redis.setObject(key, object);
}else{
redis.setex(key,Integer.parseInt(timeout+""),object);
redis.setexObject(key,object,timeout);
}
}
@ -173,12 +165,12 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public void deleteObject(String key) {
redis.del(key);
redis.deleteObject(key);
}
@Override
public long getObjectTimeout(String key) {
return redis.ttl(key);
return redis.getObjectTimeout(key);
}
/**
@ -195,11 +187,11 @@ public class SaTokenDaoRedis implements SaTokenDao {
// 如果其已经被设置为永久则不作任何处理
} else {
// 如果尚未被设置为永久那么再次set一次
this.set(key, this.get(key), timeout);
this.setObject(key, this.get(key), timeout);
}
return;
}
redis.expire(key,Integer.parseInt(timeout+""));
redis.expireObject(key,timeout);
}
/**

View File

@ -26,7 +26,7 @@
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal-undertow</artifactId>
<version>2.7</version>
<version>2.8</version>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
@ -54,7 +54,6 @@
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>

View File

@ -0,0 +1,70 @@
package cn.dev33.satoken.jfinal;
import com.jfinal.kit.LogKit;
import com.jfinal.plugin.redis.serializer.ISerializer;
import com.jfinal.plugin.redis.serializer.JdkSerializer;
import redis.clients.jedis.util.SafeEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SaJdkSerializer implements ISerializer {
public static final ISerializer me = new JdkSerializer();
public byte[] keyToBytes(String key) {
return SafeEncoder.encode(key);
}
public String keyFromBytes(byte[] bytes) {
return SafeEncoder.encode(bytes);
}
public byte[] fieldToBytes(Object field) {
return valueToBytes(field);
}
public Object fieldFromBytes(byte[] bytes) {
return valueFromBytes(bytes);
}
public byte[] valueToBytes(Object value) {
ObjectOutputStream objectOut = null;
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(1024);
objectOut = new ObjectOutputStream(bytesOut);
objectOut.writeObject(value);
objectOut.flush();
return bytesOut.toByteArray();
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
if(objectOut != null)
try {objectOut.close();} catch (Exception e) {
LogKit.error(e.getMessage(), e);}
}
}
public Object valueFromBytes(byte[] bytes) {
if(bytes == null || bytes.length == 0)
return null;
ObjectInputStream objectInput = null;
try {
ByteArrayInputStream bytesInput = new ByteArrayInputStream(bytes);
objectInput = new ObjectInputStream(bytesInput);
return objectInput.readObject();
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
if (objectInput != null)
try {objectInput.close();} catch (Exception e) {LogKit.error(e.getMessage(), e);}
}
}
}

View File

@ -29,7 +29,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public String get(String key) {
return redis.get(key);
return redis.getJedis().get(key);
}
/**
@ -44,9 +44,9 @@ public class SaTokenDaoRedis implements SaTokenDao {
return;
}
if(timeout == SaTokenDao.NEVER_EXPIRE) {
redis.set(key, value);
redis.getJedis().set(key, value);
}else{
redis.setex(key,Integer.parseInt(timeout+""),value);
redis.getJedis().setex(key,timeout,value);
}
}
@ -71,7 +71,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public void delete(String key) {
redis.del(key);
redis.getJedis().del(key);
}
/**
@ -81,7 +81,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
*/
@Override
public long getTimeout(String key) {
return redis.ttl(key);
return redis.getJedis().ttl(key);
}
/**
@ -102,7 +102,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
return;
}
redis.expire(key,Integer.parseInt(timeout+""));
redis.getJedis().expire(key,timeout);
}
/**