Redis通用模块
由于 Redis 在很多模块中都可能会用到,因此需要将其抽取出来单独的作为一个模块 ruoyi-common-redis, 别的模块想使用 Redis,只需要引入自定义的 ruoyi-common-redis 模块即可。
创建通用模块的父模块
通用的模块可能不止 一个,因此需要创建 通用模块的父工程 ruoyi-common,其余通用模块继承它就可以。
新建模块 ruoyi-common ,其 pom.xml 内容为:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>ruoyi</artifactId><groupId>com.ruoyi</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><packaging>pom</packaging><modules><module>ruoyi-common-redis</module></modules><artifactId>ruoyi-common</artifactId></project>
创建Redis通用模块
创建 ruoyi-common-redis 模块,其父模块为 ruoyi-common。其 pom.xml 文件内容:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>ruoyi-common</artifactId><groupId>com.ruoyi</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>ruoyi-common-redis</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies></project>
版本号声明
在 父工程 ruoyi 中定义 ruoyi-common-redis 模块的版本号。
<properties><ruoyi.version>1.0.0</ruoyi.version></properties><dependency><groupId>com.ruoyi</groupId><artifactId>ruoyi-common-redis</artifactId><version>${ruoyi.version}</version></dependency>
Redis使用
引入依赖
<dependency><groupId>com.ruoyi</groupId><artifactId>ruoyi-common-redis</artifactId></dependency>
编写测试代码
package com.ruoyi.system.controller;import com.ruoyi.system.api.domain.SysUser;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class TestRedisController {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@GetMapping("/testStringRedisTemplate")public void testStringRedisTemplate() {stringRedisTemplate.opsForValue().set("name","马小六");}@GetMapping("/testRedisTemplate")public void testRedisTemplate() {SysUser user = new SysUser();user.setUserId(1L);user.setNickName("张无忌");user.setUserName("zwj");user.setEmail("23@qq.com");redisTemplate.opsForValue().set("user",user);}}
测试结果
请求:http://localhost:9201/testRedisTemplate
优化改进
从上图中的测试结果,我们可以看出当我们把一个 Object对象存放到 Redis 中是,它的 Key 和 value 都是这种十六进制的。我们希望 key 是字符串, value 是 JSON 格式的对象
Redis 配置
引入依赖
在 ruoyi-common-redis 模块中引入依赖
<!-- Jackson --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- Alibaba Fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency>
版本号声明
<properties><fastjson.version>1.2.75</fastjson.version></properties><!-- JSON 解析器和生成器 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency>
Redis值的序列号
package com.ruoyi.common.redis.configure;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.ParserConfig;import com.alibaba.fastjson.serializer.SerializerFeature;import com.fasterxml.jackson.databind.JavaType;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.type.TypeFactory;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.SerializationException;import org.springframework.util.Assert;import java.nio.charset.Charset;public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {@SuppressWarnings("unused")private ObjectMapper objectMapper = new ObjectMapper();public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");private Class<T> clazz;static {ParserConfig.getGlobalInstance().setAutoTypeSupport(true);}public FastJson2JsonRedisSerializer(Class<T> clazz) {super();this.clazz = clazz;}@Overridepublic byte[] serialize(T t) throws SerializationException {if (t == null) {return new byte[0];}return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);}@Overridepublic 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);}public void setObjectMapper(ObjectMapper objectMapper) {Assert.notNull(objectMapper, "'objectMapper' must not be null");this.objectMapper = objectMapper;}protected JavaType getJavaType(Class<?> clazz) {return TypeFactory.defaultInstance().constructType(clazz);}}
Redis配置类
key使用 StringRedisSerializer 序列号, value 使用 FastJson2JsonRedisSerializer 序列号
package com.ruoyi.common.redis.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import com.ruoyi.common.redis.configure.FastJson2JsonRedisSerializer;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {@Bean@SuppressWarnings(value = {"unchecked", "rawtypes", "deprecation"})public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);serializer.setObjectMapper(mapper);template.setValueSerializer(serializer);// 使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());template.afterPropertiesSet();return template;}}
redisTemplate 二次封装
package com.ruoyi.common.redis.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.BoundSetOperations;import org.springframework.data.redis.core.HashOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Component;import java.util.*;import java.util.concurrent.TimeUnit;@Componentpublic class RedisService {@Autowiredpublic 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);}/*** 获得缓存的基本对象。** @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);}}
组件扫描
默认情况下,SpringBoot包扫描的路径为 main 方法所在类的包及其子包。在这里也就是扫描 com.ruoyi.system 包及其子包,而我们的 RedisService 组件是在 com.ruoyi.common.redis.service。为了能够扫描到,我们需求修改包扫描路径为:com.ruoyi
@MapperScan("com.ruoyi.system.mapper")@EnableDiscoveryClient@SpringBootApplication(scanBasePackages = {"com.ruoyi"})public class RuoYiSystemApplication {
测试
测试类
@Autowiredprivate RedisService redisService;@GetMapping("/testRedisService")public void testRedisService() {SysUser user = new SysUser();user.setUserId(1L);user.setNickName("张无忌");user.setUserName("zwj");user.setEmail("23@qq.com");redisService.setCacheObject("user",user);}
测试结果

