以下内容是在学习若依-微服务源码的学习总结,主要内容为 若依-微服务中如何配置
Redis
以及采用的序列化和反序列化方式。
在若依-微服务版的ruoyi-common-redis
模块中,只完成一个功能,提供 redis
工具类。
首先若依-微服务使用的 redis
为 spring-boot-starter-data-redis
,spring-data-redis
是 spring
对 redis
的封装。
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在该模块中主要有三个文件,具体作用如下:
-
FastJson2JsonRedisSerializer
:是RedisSerializer
接口的实现类,使用Fastjson
自定义序列化和反序列化方式。 -
RedisConfig
:继承于CachingConfigurerSupport
,向Spring
容器中注入一个采用自定义序列化的RedisTemplate的Bean
。 -
RedisService
:Redis
工具类。通过RedisTemplate
操作Redis
中的数据。
FastJson2JsonRedisSerializer
提供一种使用FastJson
的序列化方式,主要提供了将任意类型的数据转储为字节数组和将字节数组转储为字符串。也就是序列化和反序列化方法。核心代码如下:
// 序列化:将任意类型的数据转储为字节数组
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
// 反序列化:将字节数组转储为字符串
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
在若依-微服务中RedisConfig
为 Redis
的配置类,主要提供了 RedisTemplate
实例。
通过RedisAutoConfiguration
源码,我们可以发现Redis
提供了两个模板类 RedisTemplate
、StringRedisTemplate
。
其中RedisTemplate
默认使用 JdkSerializationRedisSerializer
进行序列化和反序列化,并且可以接受任意类型的参数。
而 StringRedisTemplate
默认使用 StringRedisSerializer
进行序列化和反序列化,并且只支持 String
类型的参数。
而我们要做的工作主要是将原本 RedisTemplate
模板类使用的默认序列化方式改成我们自定义的 FastJson
序列化方式,即FastJson2JsonRedisSerializer
。
代码如下:
@Configuration
@EnableCaching // 开启缓存
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" }) // 该注解表示忽略代码警告
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
// 获取一个默认的 RedisTemplate 实例
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// 获取我们自定义的 FastJson 序列化和反序列化方式
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// 这里不太明白,在若依源码中 set 了 ObjectMapper ,但又没有使用。
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// value 使用 自定义 FastJSON 来序列化和反序列化
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// hashvalue 使用 自定义 FastJSON 来序列化和反序列化
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
RedisService
工具类,主要使用RedisTemplate
实例对 Redis
操作进行封装。
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisService
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value)
{
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
{
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout)
{
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit)
{
return redisTemplate.expire(key, timeout, unit);
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public Boolean hasKey(String key)
{
return redisTemplate.hasKey(key);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key)
{
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection)
{
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key)
{
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key)
{
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
{
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key)
{
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey)
{
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
{
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern)
{
return redisTemplate.keys(pattern);
}
}
最后别忘了,如果是微服务项目,需要在
resources/META-INF/spring.factories
配置文件中开启自动配置,将RedisConfig
配置文件注入到Spring
容器中,方便之后的使用。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.redis.configure.RedisConfig,\
com.ruoyi.common.redis.service.RedisService