SpringBoot中整合Redis的简单封装及应用

78 阅读8分钟

配置文件

@EnableCaching
@Configuration
public class RedisConfig<K extends Serializable, E> {
 
    /**
     * key序列化方式
     */
    private final StringRedisSerializer keySerializer = new StringRedisSerializer();
    @Resource
    private RedisConnectionFactory factory;
    /**
     * value序列化方式
     */
    private Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

    {
 
        //解决缓存转换异常的问题
        ObjectMapper objectMapper = new ObjectMapper();
        //下面两行解决Java8新日期API序列化问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        //设置所有访问权限以及所有的实际类型都可序列化和反序列化
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        valueSerializer.setObjectMapper(objectMapper);
    }


    /**
     * 在Redis中以String保存键、以byte的形式保存值
     *
     * @return
     */
    @Bean
    public RedisTemplate<K, E> byteRedisTemplate() {
 
        final RedisTemplate<K, E> redisTemplate = new RedisTemplate<>();
        //设置key的序列化规则
        redisTemplate.setKeySerializer(keySerializer);
        // hash的key的序列化规则
        redisTemplate.setHashKeySerializer(keySerializer);

        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }

    /**
     * 在Redis中以String保存键、以json的形式保存值
     *
     * @return
     */
    @Bean
    public RedisTemplate<K, E> jsonRedisTemplate() {
 
        final RedisTemplate<K, E> redisTemplate = new RedisTemplate<>();
        //设置key的序列化规则
        redisTemplate.setKeySerializer(keySerializer);
        // hash的key的序列化规则
        redisTemplate.setHashKeySerializer(keySerializer);

        //hash的value的序列化规则,如果不指定默认是以二进制形式保存的
        redisTemplate.setHashValueSerializer(valueSerializer);
        //设置value的序列化规则
        redisTemplate.setValueSerializer(valueSerializer);

        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }

    //用来设置@Cacheable@CachePut@CacheEvict
    @Bean(name = "cacheManager")
    public RedisCacheManager cacheManager() {
 
        // 配置序列化(解决乱码的问题),通过config对象对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存的默认过期时间
                .entryTtl(Duration.ofDays(7))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
                // 不缓存空值
                .disableCachingNullValues();
        //缓存配置
        Map<String, RedisCacheConfiguration> cacheConfig = new HashMap<>();

        //根据redis缓存配置和reid连接工厂生成redis缓存管理器
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .transactionAware()
                .withInitialCacheConfigurations(cacheConfig)
                .build();
        return redisCacheManager;
    }
}
@Component
public class BaseRedisUtil<E> {
 

    /**
     * 过期时间一周
     */
    private static final long WEEK_SECONDS = 7 * 24 * 60 * 60;

    @Setter
    private RedisTemplate<String, E> redisTemplate;

    ///common///

    /**
     * 列举出所有的key的集合
     *
     * @return
     */
    public Set<String> keys(String pattern) {
 
        try {
 
            Set<String> keys = redisTemplate.keys(pattern);
            return keys;
        } catch (Exception e) {
 
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 指定缓存失效时间
     *
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, long time) {
 
        try {
 
            if (time > 0) {
 
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key
     * @return
     */
    public long getExpire(String key) {
 
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
 
        try {
 
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key
     */
    public boolean del(String... key) {
 
        if (key != null && key.length > 0) {
 
            if (key.length == 1) {
 
                redisTemplate.delete(key[0]);
            } else {
 
                redisTemplate.delete(Arrays.asList(key));
            }
            return true;
        }
        return false;
    }

    String

    /**
     * 普通缓存放入,永不过期
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, E value) {
 
        try {
 
            //boundValueOps()
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)
     *
     * @param key
     * @param value
     * @return
     */
    public E getSet(String key, E value) {
 
        try {
 
            final E res = redisTemplate.opsForValue().getAndSet(key, value);
            return res;
        } catch (Exception e) {
 
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key
     * @param value
     * @param expireTime 如果值为null,则使用默认的一周过期;如果值小于0则永不过期
     * @return
     */
    public boolean set(String key, E value, Long expireTime) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForValue().set(key, value, WEEK_SECONDS, TimeUnit.SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
                } else {
 
                    //永不过期
                    redisTemplate.opsForValue().set(key, value);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 批量添加String
     *
     * @param map
     * @return
     */
    public boolean multiSet(Map<String, E> map) {
 
        try {
 
            redisTemplate.opsForValue().multiSet(map);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存获取
     *
     * @param key
     * @return
     */
    public E get(String key) {
 
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 批量获取
     *
     * @param keys
     * @return
     */
    public List<E> multiGet(Collection<String> keys) {
 
        return redisTemplate.opsForValue().multiGet(keys);
    }


    ///Map/hash//

    /**
     * 向一张hash表中放入数据,永不过期
     *
     * @param key
     * @param entryKey
     * @param entryValue
     * @return
     */
    public boolean hset(String key, String entryKey, E entryValue) {
 
        try {
 
            redisTemplate.opsForHash().put(key, entryKey, entryValue);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key
     * @param entryKey
     * @param entryValue
     * @param expireTime 如果值为null则使用默认一周不过期;如果<0则永不过期
     * @return
     */
    public boolean hset(String key, String entryKey, E entryValue, Long expireTime) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForHash().put(key, entryKey, entryValue);
                //默认过期时间
                expire(key, WEEK_SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForHash().put(key, entryKey, entryValue);
                    //使用指定的过期时间
                    expire(key, expireTime);
                } else {
 
                    //永不过期
                    hset(key, entryKey, entryValue);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将Map中的元素放入set中,永不过期
     *
     * @param key
     * @param map
     * @return
     */
    public boolean hmset(String key, Map<String, E> map) {
 
        try {
 
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key
     * @param map
     * @param expireTime 如果值为null则使用默认一周不过期;如果<0则永不过期
     * @return
     */
    public boolean hmset(String key, Map<String, E> map, Long expireTime) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForHash().putAll(key, map);
                //默认过期时间
                expire(key, WEEK_SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForHash().putAll(key, map);
                    //使用指定的过期时间
                    expire(key, expireTime);
                } else {
 
                    //永不过期
                    hmset(key, map);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashGet
     *
     * @param key
     * @param entryKey
     * @return
     */
    public E hget(String key, String entryKey) {
 
        final HashOperations<String, String, E> ops = redisTemplate.opsForHash();
        return ops.get(key, entryKey);
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key
     * @return
     */
    public Map<String, E> hmget(String key) {
 
        final HashOperations<String, String, E> ops = redisTemplate.opsForHash();
        return ops.entries(key);
    }

    /**
     * 删除hash表中的值
     *
     * @param key
     * @param entryKey
     */
    public boolean hdel(String key, String... entryKey) {
 
        return redisTemplate.opsForHash().delete(key, entryKey) > 0;
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key
     * @param entryKey
     * @return
     */
    public boolean hHasKey(String key, String entryKey) {
 
        return redisTemplate.opsForHash().hasKey(key, entryKey);
    }

    //set///

    /**
     * 将数据放入set缓存,永不过期
     *
     * @param key
     * @param values
     * @return
     */
    public long sSet(String key, E... values) {
 
        try {
 
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
 
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key
     * @param expireTime
     * @param values
     * @return
     */
    public boolean sSet(String key, Long expireTime, E... values) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForSet().add(key, values);
                //默认过期时间
                expire(key, WEEK_SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForSet().add(key, values);
                    //默认过期时间
                    expire(key, expireTime);
                } else {
 
                    //永不过期
                    sSet(key, values);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key获取Set中的所有值
     *
     * @param key
     * @return
     */
    public Set<E> sGet(String key) {
 
        try {
 
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
 
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从set中查询是否存在
     *
     * @param key
     * @param value
     * @return
     */
    public boolean sHasValue(String key, E value) {
 
        try {
 
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key
     * @return
     */
    public long sGetSetSize(String key) {
 
        try {
 
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
 
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的元素
     *
     * @param key
     * @param values
     * @return
     */
    public long setRemove(String key, E... values) {
 
        try {
 
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
 
            e.printStackTrace();
            return 0;
        }
    }

    /list

    /**
     * 将value放入缓存,永不过期
     *
     * @param key
     * @param value
     * @return
     */
    public boolean lSet(String key, E value) {
 
        try {
 
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将value放入缓存,同时指定过期时间
     *
     * @param key
     * @param value
     * @param expireTime
     * @return
     */
    public boolean lSet(String key, E value, Long expireTime) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForList().rightPush(key, value);
                //默认过期时间
                expire(key, WEEK_SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForList().rightPush(key, value);
                    //使用指定的过期时间
                    expire(key, expireTime);
                } else {
 
                    //永不过期
                    sSet(key, value);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean lSets(String key, List<E> value) {
 
        try {
 
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存,同时指定过期时间
     *
     * @param key
     * @param value
     * @param expireTime
     * @return
     */
    public boolean lSets(String key, List<E> value, Long expireTime) {
 
        try {
 
            if (expireTime == null) {
 
                redisTemplate.opsForList().rightPushAll(key, value);
                //默认过期时间
                expire(key, WEEK_SECONDS);
            } else {
 
                if (expireTime > 0) {
 
                    redisTemplate.opsForList().rightPushAll(key, value);
                    //使用指定的过期时间
                    expire(key, expireTime);
                } else {
 
                    //永不过期
                    lSets(key, value);
                }
            }
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取list缓存指定范围的数据
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<E> lGet(String key, Long start, Long end) {
 
        try {
 
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
 
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key
     * @return
     */
    public long lGetListSize(String key) {
 
        try {
 
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
 
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取list缓存中指定索引的值
     *
     * @param key
     * @param index
     * @return
     */
    public E lGetIndex(String key, Long index) {
 
        try {
 
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
 
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 修改list中的指定索引处的数据
     *
     * @param key
     * @param index
     * @param value
     * @return
     */
    public boolean lUpdateIndex(String key, Long index, E value) {
 
        try {
 
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
 
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 从list中移除N个值为value的数据
     *
     * @param key
     * @param count
     * @param value
     * @return
     */
    public long lRemove(String key, Long count, E value) {
 
        try {
 
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
 
            e.printStackTrace();
            return 0;
        }
    }
}

为了实际应用中方便工具类的使用,特针对插入值为bytecode和JSON类型分别提代价工具类的两个实现类

key是字符串Value是Json的工具类实现类

@Component
public class JsonRedisUtil<E> extends BaseRedisUtil<E> {
 
    @Resource
    private RedisTemplate<String, E> jsonRedisTemplate;

    @PostConstruct
    public void init() {
 
        setRedisTemplate(jsonRedisTemplate);
    }

    /**
     * 递增
     *
     * @param key
     * @param delta
     * @return
     */
    public long incr(String key, long delta) {
 
        if (delta < 0) {
 
            throw new RuntimeException("递增因子必须大于0");
        }
        return jsonRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key
     * @param delta
     * @return
     */
    public long decr(String key, long delta) {
 
        if (delta < 0) {
 
            throw new RuntimeException("递减因子必须大于0");
        }
        return jsonRedisTemplate.opsForValue().increment(key, -delta);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key
     * @param entryKey
     * @param by
     * @return
     */
    public double hincr(String key, String entryKey, Double by) {
 
        return jsonRedisTemplate.opsForHash().increment(key, entryKey, by);
    }

    /**
     * hash递减
     *
     * @param key
     * @param entryKey
     * @param by
     * @return
     */
    public double hdecr(String key, String entryKey, Double by) {
 
        return jsonRedisTemplate.opsForHash().increment(key, entryKey, -by);
    }

}

key是字符串Value是bytecode的工具类实现类

@Component
public class ByteRedisUtil<E> extends BaseRedisUtil<E> {
 

    @Resource
    private RedisTemplate<String, E> byteRedisTemplate;

    @PostConstruct
    public void init() {
 
        setRedisTemplate(byteRedisTemplate);
    }

}

当JsonRedisUtil和ByteRedisUtil继承BaseRedisUtil时,需要给BaseRedisUtil类的redisTemplate赋不同的值:

此时使用@PostConstruct给父类的redisTemplate赋值就可以了。

@PostConstruct注解被用来修饰一个非静态的返回值为void的方法。

被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

测试实体类:Province

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Province implements Serializable {
 

    @Serial
    private static final long serialVersionUID = -5425202191700860128L;

    private Long id;

    @NotBlank(message = "省名不能为空")
    @Length(max = 8, message = "省名最多只能是8个字符")
    private String name;

    @NotBlank(message = "大区不能为空")
    private String area;

    @NotNull(message = "显示优先级不能为空")
    @Min(value = 0, message = "显示优先级最小值为0")
    private Integer priority;

    @NotNull(message = "状态不能为空")
    @Min(value = 1, message = "状态最小值为1")
    @Max(value = 2, message = "状态最大值为2")
    private Integer state;
}

JsonRedisUtilTest

@SpringBootTest
public class JsonRedisUtilTest {
 
    @Resource
    private JsonRedisUtil<Province> provinceJsonRedisUtil;
    //测试自增自减
   
@Resource
    private JsonRedisUtil<Long> longJsonRedisUtil;

    @Test
    void testKey() {
 
        final Set<String> keys = provinceJsonRedisUtil.keys("");
        System.out.println(keys);

        provinceJsonRedisUtil.getExpire("list1");
        provinceJsonRedisUtil.expire("list1", 60);

        System.out.println(provinceJsonRedisUtil.exists("list2"));

        provinceJsonRedisUtil.del("list1", "list2", "list3");
    }

    @Test
    void testString() {
 
        provinceJsonRedisUtil.set("str1", DataUtil.build(Province.class));
        provinceJsonRedisUtil.set("str2", DataUtil.build(Province.class), null);
        provinceJsonRedisUtil.set("str3", DataUtil.build(Province.class), 300L);
        provinceJsonRedisUtil.set("str4", DataUtil.build(Province.class), -1L);

        final HashMap<String, Province> map = new HashMap<>();
        map.put("p1", DataUtil.build(Province.class));
        map.put("p2", DataUtil.build(Province.class));
        map.put("p3", DataUtil.build(Province.class));
        map.put("p4", DataUtil.build(Province.class));
        provinceJsonRedisUtil.multiSet(map);

        final Province province = provinceJsonRedisUtil.get("str1");
        System.out.println(province);

        provinceJsonRedisUtil.getSet("p3", Province.builder().name("haha").area("xixi").build());
        final List<Province> list = provinceJsonRedisUtil.multiGet(List.of("p1", "p2", "p3"));
        list.forEach(System.out::println);
    }

    @Test
    void testHash() {
 
        provinceJsonRedisUtil.hset("hash11", "P1001", DataUtil.build(Province.class));
        provinceJsonRedisUtil.hset("hash12", "P1002", DataUtil.build(Province.class), null);
        provinceJsonRedisUtil.hset("hash13", "P1003", DataUtil.build(Province.class), 300L);
        provinceJsonRedisUtil.hset("hash14", "P1004", DataUtil.build(Province.class), -1L);

        Map<String, Province> map = new HashMap<>();
        map.put("P1005", DataUtil.build(Province.class));
        map.put("P1006", DataUtil.build(Province.class));
        map.put("P1007", DataUtil.build(Province.class));
        map.put("P1008", DataUtil.build(Province.class));
        provinceJsonRedisUtil.hmset("hash1", map);

        provinceJsonRedisUtil.hmset("hash2", map, null);
        provinceJsonRedisUtil.hmset("hash3", map, 300L);
        provinceJsonRedisUtil.hmset("hash4", map, -1L);

        final Province province = provinceJsonRedisUtil.hget("hash1", "P1001");
        System.out.println(province);

        final Map<String, Province> res = provinceJsonRedisUtil.hmget("hash1");
        res.forEach((k, v) -> System.out.println(k + " " + v));

        provinceJsonRedisUtil.hdel("hash4", "p1005", "p1006", "p1008");

        final boolean hasKey = provinceJsonRedisUtil.hHasKey("hash3", "p1003");
        System.out.println(hasKey);
    }

    @Test
    void testSet() {
 
        provinceJsonRedisUtil.sSet("set1", DataUtil.build(Province.class));

        final Province[] provinces = {
 DataUtil.build(Province.class), DataUtil.build(Province.class),
                DataUtil.build(Province.class), new Province()};
        provinceJsonRedisUtil.sSet("set2", null, provinces);
        provinceJsonRedisUtil.sSet("set3", 300L, provinces);
        provinceJsonRedisUtil.sSet("set4", -1L, provinces);

        final boolean r2 = provinceJsonRedisUtil.sHasValue("set4", new Province());
        System.out.println(r2);

        final long r3 = provinceJsonRedisUtil.sGetSetSize("set4");
        System.out.println(r3);

        provinceJsonRedisUtil.setRemove("set4", new Province());
        final Set<Province> r4 = provinceJsonRedisUtil.sGet("set4");
        r4.forEach(System.out::println);
    }

    @Test
    void testList() {
 
        provinceJsonRedisUtil.lSet("list1", DataUtil.build(Province.class));
        provinceJsonRedisUtil.lSet("list2", DataUtil.build(Province.class), null);
        provinceJsonRedisUtil.lSet("list3", DataUtil.build(Province.class), 300L);
        provinceJsonRedisUtil.lSet("list4", DataUtil.build(Province.class), -1L);

        List<Province> list = new ArrayList<>();
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));

        provinceJsonRedisUtil.lSets("list5", list);
        provinceJsonRedisUtil.lSets("list6", list, null);
        provinceJsonRedisUtil.lSets("list7", list, 300L);
        provinceJsonRedisUtil.lSets("list8", list, -1L);

        final List<Province> r1 = provinceJsonRedisUtil.lGet("list8", 1L, 3L);
        System.out.println(r1);

        final long length = provinceJsonRedisUtil.lGetListSize("list8");
        System.out.println(length);

        final Province r2 = provinceJsonRedisUtil.lGetIndex("list8", 3L);
        System.out.println(r2);

        final List<Province> list1 = provinceJsonRedisUtil.lGet("list8", 0L, -1L);
        list1.forEach(System.out::println);
        provinceJsonRedisUtil.lUpdateIndex("list8", 3L, DataUtil.build(Province.class));
        final List<Province> list2 = provinceJsonRedisUtil.lGet("list8", 0L, -1L);
        list2.forEach(System.out::println);

        provinceJsonRedisUtil.lSets("list9", List.of(new Province(), new Province(), new Province(), new Province()));
        provinceJsonRedisUtil.lRemove("list9", 2L, new Province());
        final List<Province> list3 = provinceJsonRedisUtil.lGet("list9", 0L, -1L);
        list3.forEach(System.out::println);
    }

    @Test
    void fun22() {
 
        longJsonRedisUtil.set("id2", 88L);
        longJsonRedisUtil.incr("id2", 100);
        longJsonRedisUtil.decr("id2", 50);

        longJsonRedisUtil.hset("hashid", "ID", 88L);
        longJsonRedisUtil.hincr("hashid", "ID", 100D);
        longJsonRedisUtil.hdecr("hashid", "ID", 50D);
    }
}

具体存储在Redis中的数据是Json形式的,比如:

ByteRedisUtilTest

@SpringBootTest
public class ByteRedisUtilTest {
 

    @Resource
    private ByteRedisUtil<Province> provinceByteRedisUtil;

    @Test
    void testKey() {
 
        final Set<String> keys = provinceByteRedisUtil.keys("");
        System.out.println(keys);

        provinceByteRedisUtil.getExpire("list1");
        provinceByteRedisUtil.expire("list1", 60);

        System.out.println(provinceByteRedisUtil.exists("list2"));

        provinceByteRedisUtil.del("list1", "list2", "list3");
    }

    @Test
    void testString() {
 
        provinceByteRedisUtil.set("str1", DataUtil.build(Province.class));
        provinceByteRedisUtil.set("str2", DataUtil.build(Province.class), null);
        provinceByteRedisUtil.set("str3", DataUtil.build(Province.class), 300L);
        provinceByteRedisUtil.set("str4", DataUtil.build(Province.class), -1L);

        final HashMap<String, Province> map = new HashMap<>();
        map.put("p1", DataUtil.build(Province.class));
        map.put("p2", DataUtil.build(Province.class));
        map.put("p3", DataUtil.build(Province.class));
        map.put("p4", DataUtil.build(Province.class));
        provinceByteRedisUtil.multiSet(map);

        final Province province = provinceByteRedisUtil.get("str1");
        System.out.println(province);

        provinceByteRedisUtil.getSet("p3", Province.builder().name("haha").area("xixi").build());

        final List<Province> list = provinceByteRedisUtil.multiGet(List.of("p1", "p2", "p3"));
        list.forEach(System.out::println);
    }

    @Test
    void testHash() {
 
        provinceByteRedisUtil.hset("hash11", "P1001", DataUtil.build(Province.class));
        provinceByteRedisUtil.hset("hash12", "P1002", DataUtil.build(Province.class), null);
        provinceByteRedisUtil.hset("hash13", "P1003", DataUtil.build(Province.class), 300L);
        provinceByteRedisUtil.hset("hash14", "P1004", DataUtil.build(Province.class), -1L);

        Map<String, Province> map = new HashMap<>();
        map.put("P1005", DataUtil.build(Province.class));
        map.put("P1006", DataUtil.build(Province.class));
        map.put("P1007", DataUtil.build(Province.class));
        map.put("P1008", DataUtil.build(Province.class));
        provinceByteRedisUtil.hmset("hash1", map);

        provinceByteRedisUtil.hmset("hash2", map, null);
        provinceByteRedisUtil.hmset("hash3", map, 300L);
        provinceByteRedisUtil.hmset("hash4", map, -1L);

        final Province province = provinceByteRedisUtil.hget("hash1", "P1001");
        System.out.println(province);

        final Map<String, Province> res = provinceByteRedisUtil.hmget("hash1");
        res.forEach((k, v) -> System.out.println(k + " " + v));

        provinceByteRedisUtil.hdel("hash4", "p1005", "p1006", "p1008");

        final boolean hasKey = provinceByteRedisUtil.hHasKey("hash3", "p1003");
        System.out.println(hasKey);
    }

    @Test
    void testSet() {
 
        provinceByteRedisUtil.sSet("set1", DataUtil.build(Province.class));

        final Province[] provinces = {
 DataUtil.build(Province.class), DataUtil.build(Province.class),
                DataUtil.build(Province.class), new Province()};
        provinceByteRedisUtil.sSet("set2", null, provinces);
        provinceByteRedisUtil.sSet("set3", 300L, provinces);
        provinceByteRedisUtil.sSet("set4", -1L, provinces);

        final boolean r2 = provinceByteRedisUtil.sHasValue("set4", new Province());
        System.out.println(r2);

        final long r3 = provinceByteRedisUtil.sGetSetSize("set4");
        System.out.println(r3);

        provinceByteRedisUtil.setRemove("set4", new Province());
        final Set<Province> r4 = provinceByteRedisUtil.sGet("set4");
        r4.forEach(System.out::println);
    }

    @Test
    void testList() {
 
        provinceByteRedisUtil.lSet("list1", DataUtil.build(Province.class));
        provinceByteRedisUtil.lSet("list2", DataUtil.build(Province.class), null);
        provinceByteRedisUtil.lSet("list3", DataUtil.build(Province.class), 300L);
        provinceByteRedisUtil.lSet("list4", DataUtil.build(Province.class), -1L);

        List<Province> list = new ArrayList<>();
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));
        list.add(DataUtil.build(Province.class));

        provinceByteRedisUtil.lSets("list5", list);
        provinceByteRedisUtil.lSets("list6", list, null);
        provinceByteRedisUtil.lSets("list7", list, 300L);
        provinceByteRedisUtil.lSets("list8", list, -1L);

        final List<Province> r1 = provinceByteRedisUtil.lGet("list8", 1L, 3L);
        System.out.println(r1);

        final long length = provinceByteRedisUtil.lGetListSize("list8");
        System.out.println(length);

        final Province r2 = provinceByteRedisUtil.lGetIndex("list8", 3L);
        System.out.println(r2);

        final List<Province> list1 = provinceByteRedisUtil.lGet("list8", 0L, -1L);
        list1.forEach(System.out::println);
        provinceByteRedisUtil.lUpdateIndex("list8", 3L, DataUtil.build(Province.class));
        final List<Province> list2 = provinceByteRedisUtil.lGet("list8", 0L, -1L);
        list2.forEach(System.out::println);

        provinceByteRedisUtil.lSets("list9", List.of(new Province(), new Province(), new Province(), new Province()));
        provinceByteRedisUtil.lRemove("list9", 2L, new Province());
        final List<Province> list3 = provinceByteRedisUtil.lGet("list9", 0L, -1L);
        list3.forEach(System.out::println);
    }

}

具体存储在Redis中的数据是bytecode形式的,比如: