SpringBoot集成Redis及Redis使用方法

 更新时间:2023年08月11日 09:16:20   作者:李指导、  
Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,这篇文章主要介绍了SpringBoot集成Redis及Redis使用方法,需要的朋友可以参考下

应用背景

将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方。 缓存就是一个存储器,在技术选型中,常用 Redis 作为缓存数据库,可以帮我们分散掉数据库的压力,有了它能更好的支持并发性能,主要是在获取资源方便性能优化的关键方面。可以这样理解redis位于数据库和springboot框架之间,起到数据缓存的作用。

Redis简介

  • Redis介绍:Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库。
  • Redis使用场景:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统
  • Redis数据类型:Redis提供的数据类型主要分为5种自有类型和一种自定义类型,这5种自有类型包括:String类型、哈希类型、列表类型、集合类型和顺序集合类型。

更新缓存模式 Cache aside这是最常用最常用的pattern了。其具体逻辑如下:

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

更新问题

  • 我们知道,在 springboot 1.5.x版本的默认的Redis客户端是 Jedis实现的,需要导入jedis依赖,而springboot 2.x版本中默认客户端是用 lettuce实现的,需要导入spring-boot-starter-data-redis依赖。这两种方式使用的都是 TCP协议。可以理解为:咱们通过程序是不能直接连接 Redis,得利用客户端工具才能进行连接。比较常用的有两种:Jedis、Lettuce。既然 Lettuce 和 Jedis 的都是连接 Redis Server 的客户端,那么它们有什么区别呢?
  • Jedis使用直连方式连接Redis Server,在多线程环境下存在线程安全问题, 因此需要增加连接池来解决线程安全的问题,同时可以限制redis客户端的数量, 但这种直连方式基于传统I/O模式,是阻塞式传输。
  • 而 Lettuce 是 一种可伸缩,线程安全,完全非阻塞的Redis客户端,底层基于netty通信,我们知道netty是基于NIO的非阻塞通信, 天生支持高并发,因此在在多线程环境下不存在线程安全问题,一个连接实例就可以满足多线程环境下的并发访问, 当然实例不够的情况下也可以按需增加实例,保证伸缩性。
  • 下面我们通过源码的方式解析springboot是如何通过lettuce方式连接redis server的,以及springboot操作redis的底层原理。      

​一:环境配置

1.1: 在pom.xml文件中添加依赖

这里说说为什么要添加 org.apache.commons 依赖,如果不加,它会报错:Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig

<dependencies>
<!-- SpringBoot集成Redis的起步依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<!--lettuce 依赖commons-pool-->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.8.0</version>
</dependency>
</dependencies>

1.2:配置SpringBoot核心配置文件application.properties

yml文件格式

spring:        
  redis:
    open: true  # 是否开启redis缓存  true开启   false关闭
    database: 0
    host: 127.0.0.1
    port: 3304
    password: 123456  # 密码(默认为空)
    timeout: 6000ms  # 连接超时时长(毫秒)
    expire: 3600 #7天不过期
    lettuce:
      pool:
        max-active: 100  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 20      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

properties文件格式

#Redis
##Redis数据库索引
spring.redis.database=0
##Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=3304
## 连接超时时间(毫秒)
spring.redis.timeout=3
## Redis服务器连接密码(默认为空)
spring.redis.password=135246
## 连接池中的最大连接数 (使用复数则标识没有限制) 默认 8
spring.redis.pool.max.active=100
## 连接池最大阻塞等待时间(使用负值表示没有限制)默认 -1
spring.redis.pool.max.wait=-1
## 连接池中的最大空闲连接 默认 8 
spring.redis.pool.max.idle=20
## 连接池中的最小空闲连接 默认 0 
spring.redis.pool.max.idle=0

二:在Config文件夹中创建RedisConfig配置文件类

RedisTemplate 是 Spring 操作 Redis 的重点内容。 RedisTemplate是一个强大的类,首先它会自动从 RedisConnectionFactory 工厂中获取连接,然后执行对应的 Redis命令,提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现,在最后还会关闭 Redis 的连接。

2.1:RedisTemplate中的几个角色:

  • RedisSerializer:由于与Redis服务器的通信一定是使用字节数组完成的,所以RedisSerializer是将Java对象编码解码的组件
  • RedisOperations:封装了一些Redis操作
  • XXXOperations:封装了指定类型或功能的数据的操作,如ZSetOperations

2.2:为什么要自定义序列化:

RedisTemplate操作时,默认会采用jdkSerializable序列化机制,使得插入的值在redis客户端看来会有乱码 类似于: "\xac\ced\x00\x05t\x00\x03key" ,所以解决这个问题就需要修改默认的序列化规则。

2.2.1:Spring 中提供了以下几个序列化器:

  • Jackson2JsonRedisSerializer
  • JdkSerializationRedisSerializer
  • OxmSerializer
  • StringRedisSerializer
  • GenericToStringRedisSerializer
  • GenericJackson2JsonRedisSerializer

本章使用的是StringRedisSerializer, String序列化方式。

RedisConfig 所在结构地址:

package com.lizexin.springbootdemo.config;
import org.springframework.beans.factory.annotation.Autowired;
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.*;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * 项目名称:springboot-demo
 * 类名称:RedisConfig
 * 类描述:Redis配置
 * 创建时间:2023/08/04
 * @author lzx
 * @version v1.0
 */
@Configuration
public class RedisConfig {
    @Autowired
    private RedisConnectionFactory factory;
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        // 将template 泛型设置为 <String, Object>
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 使用 String 序列化方式,序列化 KEY。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 使用 String 序列化方式,序列化 VALUE。
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        // 使用 String 序列化方式,序列化 HashKEY。
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // 使用 String 序列化方式,序列化 ValueKEY。
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        // 配置连接工厂
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }
    /**
     *  HashOperations
     *  操作 Hash 类型数据
     **/
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }
    /**
     *  HashOperations
     * 操作 String 类型数据
     **/
    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
        return redisTemplate.opsForValue();
    }
    /**
     *  HashOperations
     * 操作 List 类型数据
     **/
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }
    /**
     *  HashOperations
     * 操作 Set 类型数据
     **/
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }
    /**
     *  HashOperations
     * 操作 SortedSet 类型数据
     **/
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

四:封装Redis Utils工具包

Redis工具包分为三个类
1:RedisUtils.java     Redis方法类主要记录对redis的一些操作,增删改查等。
2:RedisKeys.java    Redis自定义Key类,自定义配置,对redis操作时好分辨哪个key的数据
3:UserRedis.java    封装类,将RedisUtils和RedisKey进行封装,用户直接操作此类

redis 工具包 所在结构地址:

4.1:RedisUtils.java

package com.lizexin.springbootdemo.utils.redis;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * 项目名称:springboot-demo
 * 类名称:RedisUtils
 * 类描述:Redis工具类
 * 创建时间:2023/08/04
 * @author lzx
 * @version v1.0
 */
@Component
public class RedisUtils {
    /**日志*/
    private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ValueOperations<String, String> valueOperations;
    @Autowired
    private HashOperations<String, String, Object> hashOperations;
    @Autowired
    private ListOperations<String, Object> listOperations;
    @Autowired
    private SetOperations<String, Object> setOperations;
    @Autowired
    private ZSetOperations<String, Object> zSetOperations;
    /**默认过期时长,单位: 秒*/
    public final static long DEFAULT_EXPIRE = 60 * 10;
    /**从配置文件获取 默认过期时长*/
    @Value("${spring.redis.expire}")
    public long expire;
    /**不设置过期时长 */
    public final static long NOT_EXPIRE = -1;
    /**它可以帮助我们快速的进行各个类型和Json类型的相互转换*/
    private static final ObjectMapper MAPPER = new ObjectMapper();
    /**给指定key设置固定时间的有效期*/
    public void  expireAt(String key,Date date){
        redisTemplate.expireAt(key,date);
    }
    /**根据指定的key,获取过期时间*/
    public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS);}
    /**判断key是否存在*/
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
    * 删除缓存, @param key可以传一个值 或多个
    * 该注解屏蔽某些编译时的警告信息
    * */
    @SuppressWarnings("unchecked")
    public void delete(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }
    /**将Object值放如缓存并设置默认时间,调用下一个方法将值转为JSON字符串*/
    public void set(String key, Object value){
        set(key, value, DEFAULT_EXPIRE);
    }
    /**将Object值转为JSON字符串放入缓存,并设置过期时长*/
    public void set(String key, Object value, long expire){
        valueOperations.set(key, objectToJson(value));
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
    }
    /**根据key和泛型获取值, 调用下一个get方法*/
    public <T> T get(String key, Class<T> clazz) {
        return get(key, clazz, NOT_EXPIRE);
    }
    /**根据key键获取值并转为对象 并重新设置过期时间*/
    public <T> T get(String key, Class<T> clazz, long expire) {
        String value = valueOperations.get(key);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        //将Json字符串转换为bean对象
        return value == null ? null : fromJson(value, clazz);
    }
    /**根据key键获取值返回为String*/
    public String get(String key, long expire) {
        String value = valueOperations.get(key);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        return value;
    }
    /*根据key获取值*/
    public String get(String key) {
        return get(key, NOT_EXPIRE);
    }
     /**Object转换为JSON字符串,在存reid的时候调用此方法*/
    private String objectToJson(Object object){
        if(object instanceof Integer || object instanceof Long || object instanceof Float ||
                object instanceof Double || object instanceof Boolean || object instanceof String){
            return String.valueOf(object);
        }
        return JSONUtil.toJsonStr(object);
    }
    /**JSON字符串, 转成javaBean对象*/
    private <T> T fromJson(String json, Class<T> clazz){
        return JSONUtil.toBean(json, clazz);
        //return JSON.parseObject(json,clazz);
    }
    /**将JsonObject转为实体类对象,转换异常将被抛出*/
    public static <T> T fromJsonToBean(JSONObject json, Class<T> beanClass) {
        return null == json ? null : json.toBean(beanClass);
    }
    /**将元素添加到指定set集合中*/
    public void addToSet(String key,String member){
        redisTemplate.opsForSet().add(key,member);
    }
    /**批量添加到指定set集合中*/
    public void addBatchToSet(String key,List<String> memberList) {
        Object[] members = memberList.toArray();
        redisTemplate.opsForSet().add(key,members);
    }
    /**统计指定set的长度,当指定key的set不存在时,返回null*/
    public Long countForSet(String key){
        return redisTemplate.opsForSet().size(key);
    }
    /**只有当key不存在时才设置key的值,并返回true;当key存在时不修改key的值,并返回false。*/
    public Boolean isMember(String value){
       return setOperations.isMember(RedisKeys.AutoKey,value);
    }
    /**向集合添加值并设置过期时间*/
    public Long addSetDataExpire(String value,String name,long expire){
     Long addSet =  setOperations.add(name,value);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(name, expire, TimeUnit.SECONDS);
        }
        return addSet;
    }
    /**向右边批量添加元素*/
    public boolean addrightPushAll(String key, List<Object> value) {
        boolean var4;
        try {
            this.redisTemplate.opsForList().rightPushAll(key, value);
            boolean var3 = true;
            return var3;
        } catch (Exception var8) {
            logger.error("", var8);
            var4 = false;
        } finally {
            this.close();
        }
        return var4;
    }
    /**    * 获取泛型的Collection Type
     * @param collectionClass 泛型的Collection
     * @param elementClasses 元素类
     * @return JavaType Java类型
     * @since 1.0*/
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
    private void close() {
        RedisConnectionUtils.unbindConnection(this.redisTemplate.getConnectionFactory());
    }
}

4.2:RedisKeys.java

package com.zhangtao.moguding.province.utils.redis;
/**
 * 项目名称:user-center-service
 * 类名称:RedisKeys
 * 类描述:redis所有的key
 * 创建时间:2023/7/27
 *
 * @author lzx
 * @version v1.0
 */
public class RedisKeys {
    //最大蘑菇号的key
    public final static String MAX_MOGUNO_KEY = "moguding:user:max_mogu_no";
    //短信验证码的key
    public static String getSmsCodeKey(String key,Integer type){
        return "moguding:user:smsCode:" + key+":"+type;
    }
    //权限列表
    public final static String PERMISSIONS_USERAUTH_KEY = "moguding:permissions:permissions_userauth_list:";
    //参数配置
    public static String getUserConfigKey(String... key){
        return "moguding:user:config:" + key;
    }
    //用户Token
    public final static String AUTH_TOKEN_KEY = "moguding:user:authToken:";
    //authtoken的key  web端
    public static String getAuthToken(String type,String userid){
        if("web".equals(type)){
            return AUTH_TOKEN_KEY+type+":" + userid;
        }else {
            return  getAuthToken(userid);
        }
    }
    //authtoken的key  app端
    public static String getAuthToken(String userid){
        return AUTH_TOKEN_KEY+ userid;
    }
    //缓存活跃蘑菇号key的
    public final static String ACTIVE_MOGU_NO= "moguding:user:active:";
    //缓存今日学校签到排行榜
    public final static String SCHOOL_SIGN_RANK= "moguding:school:sign:rank";
    //学校统计(实时发送【考勤,上岗,周报】)
    public final static String SCHOOL_COUNT= "moguding.school.count";
    //自动报告key
    public final static String AutoKey = "autoReport_set";
    //30天最后一次考勤
    public final static String LastSign = "moguding.last.sign";
    //省平台基础数据
    public static String getProvinceConfigKey(String key){
        return "moguding:province:config:" + key;
    }
}

4.3:UserRedis.java

package com.zhangtao.moguding.province.utils.redis;
import com.zhangtao.moguding.province.entity.UserConfigEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 项目名称:user-center-service
 * 类名称:UserRedis
 * 类描述:UserRedis
 * 创建时间:2019/5/27
 * @author lzx
 * @version v1.0
 */
/*
 *将RedisUtils的set方法和RedisKeys的key 封装到一起
 * */
@Component
public class UserRedis {
    @Autowired
    private RedisUtils redisUtils;
    public void set(String key,String value) {
        if(key == null){
            return ;
        }
        String redisKey = RedisKeys.getUserConfigKey(key);
        redisUtils.set(redisKey, value,redisUtils.expire);
    }
    public void delete(String key) {
        if(key == null){
            return ;
        }
        String redisKey = RedisKeys.getUserConfigKey(key);
        redisUtils.delete(redisKey);
    }
    public String get(String key){
        if(key == null){
            return null;
        }
        String redisKey = RedisKeys.getUserConfigKey(key);
        return redisUtils.get(redisKey);
    }
    public UserConfigEntity getObject(String key){
        if(key == null){
            return null;
        }
        String redisKey = RedisKeys.getUserConfigKey(key);
        return redisUtils.get(redisKey, UserConfigEntity.class);
    }
    //向Redis添加值,设置默认过期时长 7天, set方法将value进行序列化(转为JSON字符串)
/*    public void set(String key,Object value) {
        if(key == null){
            return ;
        }
        String redisKey = RedisKeys.getRedisTestKey(key);
        redisUtils.set(redisKey, value,redisUtils.expire);
    }
    public <T> T get(String key, Class<T> clazz){
        if(key == null){
            return null;
        }
        String redisKey = RedisKeys.getRedisTestKey(key);
        return redisUtils.get(redisKey,clazz);
    }
    //判断Redis测试key是否存在
    public boolean hasKey(String key){
        if(key == null){
            return false;
        }
        String redisKey = RedisKeys.getRedisTestKey(key);
        return redisUtils.hasKey(redisKey);
    };*/
    //将今日活跃用户的蘑菇号批量存进redis指定Set集合中
    public void addUserMoguNosToSet(List<String> moguNos){
        redisUtils.addBatchToSet(RedisKeys.ACTIVE_MOGU_NO,moguNos);
    }
    //将今日活跃用户的蘑菇号缓存Set集合清空
    public void deleteForCacheUserMoguNo(){
        redisUtils.delete(RedisKeys.ACTIVE_MOGU_NO);
    }
    //判断Redis测试key是否存在
    public boolean hasKey(String key){
        if(key == null){
            return false;
        }
        String redisKey = RedisKeys.getProvinceConfigKey(key);
        return redisUtils.hasKey(redisKey);
    };
    //从redis中统计活跃用户数量
    public int countActiveUser(){
        Long Lnum  = redisUtils.countForSet(RedisKeys.ACTIVE_MOGU_NO);
        if(Lnum==null){
            return 0;
        }else {
            return Lnum.intValue();
        }
    }
    //省级平台获取redisKey
    public String getProvinceKey(String key){
        if(key == null){
            return null;
        }
        String redisKey = RedisKeys.getProvinceConfigKey(key);
        return redisUtils.get(redisKey);
    }
    //省级平台向redis插入数据
    public void setProvinceDataToRedis(String key,String list){
        String keys = RedisKeys.getProvinceConfigKey(key);
         //配置文件默认保留时长
         redisUtils.setRedis(keys,list,redisUtils.expire);
    }
}

五:流程实现

模拟SpringBoot项目结构调用

1.RedisTestController

package com.lizexin.springbootdemo.Controller;
import com.lizexin.springbootdemo.entity.Item;
import com.lizexin.springbootdemo.service.RedisTestService;
import com.zhangtao.common.dto.response.BaseResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @program: springboot-demo
 * @author: lzx
 * @Time: 2023/8/9  16:35
 * @description: Redis测试接口
 * @version: v1.0
 */
@RestController
@Api(tags = {"Redis测试接口"},produces = "RedisTest_controller")
@RequestMapping("/redis")
public class RedisTestController {
    @Autowired
    RedisTestService redisTestService;
    private Logger logger = LoggerFactory.getLogger(RedisTestController.class);
    @ApiOperation(value = "Redis测试,将对象插入缓存",notes = "")
    @RequestMapping("/v1/test")
    public BaseResponse redisInsertBeanController(@RequestBody Item item){
        return redisTestService.redisInsertBeanService(item);
    }
    @ApiOperation(value = "Redis测试,将List插入缓存",notes = "")
    @RequestMapping("/v2/test")
    public BaseResponse redisInsertListController(@RequestBody Item item){
        return redisTestService.redisInsertListService(item);
    }
    @ApiOperation(value = "Redis测试,将Map<String,Set<String>>插入缓存,取出来转Map<String,JsonArry>",notes = "")
    @RequestMapping("/v3/test")
    public BaseResponse redisInsertMapController(@RequestBody Item item){
        return redisTestService.redisInsertMapService(item);
    }
}

 2.RedisTestService

package com.lizexin.springbootdemo.service;
import com.lizexin.springbootdemo.entity.Item;
import com.zhangtao.common.dto.response.BaseResponse;
/**
 * @program: springboot-demo
 * @author: lzx
 * @Time: 2023/8/9  22:55
 * @description: Redis测试接口Service
 * @version: v1.0
 */
public interface RedisTestService {
    BaseResponse redisInsertBeanService( Item item);
    BaseResponse redisInsertListService( Item item);
    BaseResponse redisInsertMapService( Item item);
}

3.RedisTestServiceImpl

package com.lizexin.springbootdemo.service.impl;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.lizexin.springbootdemo.entity.Item;
import com.lizexin.springbootdemo.service.RedisTestService;
import com.lizexin.springbootdemo.utils.*;
import com.lizexin.springbootdemo.utils.redis.UserRedis;
import com.zhangtao.common.dto.response.BaseResponse;
import com.zhangtao.common.dto.response.ObjectResponse;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @program: springboot-demo
 * @author: lzx
 * @Time: 2023/08/9  22:58
 * @description: test
 * @version: v1.0
 */
@Service
public class RedisTestServiceImpl implements RedisTestService {
    @Autowired
    UserRedis userRedis;
    private static final Logger logger = LoggerFactory.getLogger(RedisTestServiceImpl.class);
    @Override
    @ApiOperation(
     "通过key得到值并重新设置过期时间,若值不存在则重新插入缓存。"+
     "set方法封装了 JSONUtil.toJsonStr"+ "get带泛型的方法封装了JSONUtil.toBean "
    )
    public BaseResponse redisInsertBeanService(Item item) {
        String redisKey= "redisInsertBeanService";
        System.out.println(redisKey);
        //判断key值是否存在,如果存在则优先取缓存
        if (userRedis.hasKey(redisKey)){
            Item jsonString=  userRedis.get(redisKey,Item.class);
            logger.info("存在值");
            logger.info(jsonString.toString());
            return ObjectResponse.resObj(jsonString);
        }else{
            //不存在则缓存
           Item item1= AttributeData.list9();
           logger.info("不存在值 插入");
           userRedis.set(redisKey,item1);
            return ObjectResponse.ok();
        }
    }
    @Override
    @ApiOperation("get方法不带泛型默认返回Json字符串,需要自行反序列化")
    public BaseResponse redisInsertListService(Item item) {
        //通过key得到值,
        String redisKey = "redisInsertListService";
        System.out.println(redisKey);
        //判断key值是否存在,如果存在则优先取缓存
        if (userRedis.hasKey(redisKey)){
            List<Item> list = JSONArray.parseArray(userRedis.get(redisKey),Item.class);
            logger.info("存在值");
            logger.info(list.toString());
            return ObjectResponse.resObj(list);
        }else{
            //不存在则缓存
            List<Item> list= AttributeData.list8();
            logger.info("不存在值 插入");
            userRedis.set(redisKey,list);
            return ObjectResponse.ok();
        }
    }
    @Override
    @ApiOperation("")
    public BaseResponse redisInsertMapService(Item item) {
        //通过key得到值,
        String redisKey= "redisInsertMapService";
        System.out.println(redisKey);
        //判断key值是否存在,如果存在则优先取缓存
        if (userRedis.hasKey(redisKey)){
            String jsonString=  userRedis.get(redisKey);
            //可以通过JSonString转对象方法把Vlue值从Set转为JsonArray
            Map<String,JSONArray> arrayMap= JSONUtil.toBean(jsonString,Map.class);
            logger.info("存在值");
            logger.info(arrayMap.toString());
            return ObjectResponse.resObj(arrayMap);
        }else{
            //不存在则缓存
            List<Item> list= AttributeData.list10();
            //根据key转map,之后将Value换成set集合
            //将集合添加至Map 指定参数作为key
            Map<String,List<Item>> map = new HashMap();
            Map<String,Set<String>>setMap =new HashMap<>();
            map = list.stream().collect(Collectors.groupingBy(Item::getName,Collectors.toList()));
            for (Map.Entry<String,List<Item>> key:map.entrySet()){
                Set<String> set = new HashSet<>();
                key.getValue().forEach(c->{
                   set.add(c.getValue());
                });
                setMap.put(key.getKey(), set);
            }
            logger.info("不存在值 插入");
            userRedis.set(redisKey,setMap);
            return ObjectResponse.ok();
        }
    }
}

4.AttributeData

package com.lizexin.springbootdemo.utils;
import com.lizexin.springbootdemo.dto.CommonInterfaceDto;
import com.lizexin.springbootdemo.dto.InformationDatasDto;
import com.lizexin.springbootdemo.dto.export.ExportGxySchoolFlowDto;
import com.lizexin.springbootdemo.entity.Item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @program: springboot-demo
 * @author: lzx
 * @Time: 2023/8/9  22:55
 * @description: 常用数据集
 * @version: v1.0
 */
public class AttributeData {
        public static  List<Map<String,Object>> list1 (){
            //构建List集合1
            List<Map<String,Object>> list1 = new ArrayList<>();
            Map<String,Object> data=new HashMap<>();
            data.put("userId","100001");
            data.put("userName","唐僧");
            list1.add(data);
            data=new HashMap<>();
            data.put("userId","100002");
            data.put("userName","八戒");
            list1.add(data);
            data=new HashMap<>();
            data.put("userId","100003");
            data.put("userName","悟空");
            list1.add(data);
            data=new HashMap<>();
            data.put("userId","100004");
            data.put("userName","沙僧");
            list1.add(data);
            return list1;
        }
        public static  List<Map<String,Object>> list2(){
            Map<String,Object> data=new HashMap<>();
            List<Map<String,Object>> list2 = new ArrayList<>();
            data=new HashMap<>();
            data.put("userId","100001");
            data.put("gender","男");
            data.put("age",20);
            list2.add(data);
            data=new HashMap<>();
            data.put("userId","100002");
            data.put("gender","雄");
            data.put("age",1000);
            list2.add(data);
            data=new HashMap<>();
            data.put("userId","100003");
            data.put("gender","雄");
            data.put("age",600);
            list2.add(data);
            data=new HashMap<>();
            data.put("userId","100004");
            data.put("gender","男");
            data.put("age",800);
            list2.add(data);
            return list2;
        }
        public static List<InformationDatasDto> list3(){
            List<InformationDatasDto> list = new ArrayList<>();
            InformationDatasDto info = new InformationDatasDto();
            info.setStudentId("10000");
            info.setStudent_name("张三");
            list.add(info);
            info = new InformationDatasDto();
            info.setStudentId("10001");
            info.setStudent_name("里李四");
            list.add(info);
            info = new InformationDatasDto();
            info.setStudentId("10002");
            info.setStudent_name("王五");
            list.add(info);
            info = new InformationDatasDto();
            info.setStudentId("10003");
            info.setStudent_name("赵六");
            list.add(info);
            info = new InformationDatasDto();
            info.setStudentId("10004");
            info.setStudent_name("马七");
            list.add(info);
            return list;
        }
    public static List<InformationDatasDto> list4(){
        List<InformationDatasDto> list = new ArrayList<>();
        InformationDatasDto info = new InformationDatasDto();
        info.setStudentId("北京");
        info.setStudent_name("张三");
        list.add(info);
        info = new InformationDatasDto();
        info.setStudentId("北京省");
        info.setStudent_name("里李四");
        list.add(info);
        info = new InformationDatasDto();
        info.setStudentId("湖北省");
        info.setStudent_name("王五");
        list.add(info);
        info = new InformationDatasDto();
        info.setStudentId("湖北");
        info.setStudent_name("赵六");
        list.add(info);
        info = new InformationDatasDto();
        info.setStudentId("海南");
        info.setStudent_name("马七");
        list.add(info);
        return list;
    }
    public static List<ExportGxySchoolFlowDto> list5(){
        List<ExportGxySchoolFlowDto> list = new ArrayList<>();
        ExportGxySchoolFlowDto info = new ExportGxySchoolFlowDto();
        info.setSchoolName("齐齐哈尔大学");
        info.setDatas("黑龙江省");
        info.setValue(10);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("齐齐哈尔大学");
        info.setDatas("黑龙江");
        info.setValue(20);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("齐齐哈尔大学");
        info.setDatas("黑龙江省哈尔滨市");
        info.setValue(20);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("齐齐哈尔大学");
        info.setDatas("甘肃省");
        info.setValue(20);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("哈尔滨大学");
        info.setDatas("黑龙江");
        info.setValue(20);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("武汉职业大学");
        info.setDatas("北京市");
        info.setValue(10);
        list.add(info);
        info = new ExportGxySchoolFlowDto();
        info.setSchoolName("黑河市大学");
        info.setDatas("北京");
        info.setValue(10);
        list.add(info);
        return list;
    }
    public static List<CommonInterfaceDto.ItemBatchDataDto> list6(){
        List<CommonInterfaceDto.ItemBatchDataDto> list =new ArrayList<>();
        CommonInterfaceDto.ItemBatchDataDto item1 =new CommonInterfaceDto.ItemBatchDataDto();
        item1.setSchoolName("双高校");
        item1.setData(10);
        item1.setBatchName("19年");
        list.add(item1);
        CommonInterfaceDto.ItemBatchDataDto item2 =new CommonInterfaceDto.ItemBatchDataDto();
        item2.setSchoolName("双高校");
        item2.setData(20);
        item2.setBatchName("20年");
        list.add(item2);
        CommonInterfaceDto.ItemBatchDataDto item3 =new CommonInterfaceDto.ItemBatchDataDto();
        item3.setSchoolName("双高校");
        item3.setData(30);
        item3.setBatchName("21年");
        list.add(item3);
        CommonInterfaceDto.ItemBatchDataDto item4 =new CommonInterfaceDto.ItemBatchDataDto();
        item4.setSchoolName("双高校");
        item4.setData(40);
        item4.setBatchName("22年");
        list.add(item4);
        return list;
    }
    public static List<CommonInterfaceDto.ItemBatchDataDto> list7(){
        List<CommonInterfaceDto.ItemBatchDataDto> list =new ArrayList<>();
        CommonInterfaceDto.ItemBatchDataDto item1 =new CommonInterfaceDto.ItemBatchDataDto();
        item1.setSchoolName("郑州经贸学院");
        item1.setData(60);
        item1.setBatchName("19年");
        list.add(item1);
        CommonInterfaceDto.ItemBatchDataDto item2 =new CommonInterfaceDto.ItemBatchDataDto();
        item2.setSchoolName("郑州经贸学院");
        item2.setData(10);
        item2.setBatchName("22年");
        list.add(item2);
        return list;
    }
    public static List<Item> list8(){
        List<Item> list =new ArrayList<>();
        Item item1 =new Item();
        item1.setName("计算机");
        item1.setValue(10);
        list.add(item1);
        Item item2 =new Item();
        item2.setName("会计");
        item2.setValue(20);
        list.add(item2);
        Item item3 =new Item();
        item3.setName("销售");
        item3.setValue(30);
        list.add(item3);
        Item item4 =new Item();
        item4.setName("老师");
        item4.setValue(40);
        list.add(item4);
        Item item5 =new Item();
        item5.setName("医学");
        item5.setValue(40);
        list.add(item5);
        Item item6 =new Item();
        item6.setName("农业");
        item6.setValue(94);
        list.add(item6);
        Item item7 =new Item();
        item7.setName("工程");
        item7.setValue(100);
        list.add(item7);
        return list;
    }
    public static Item list9(){
        Item item7 =new Item();
        item7.setName("工程");
        item7.setValue(100);
        return item7;
    }
    public static List<Item> list10(){
        List<Item> list =new ArrayList<>();
        Item item1 =new Item();
        item1.setName("河南省");
        item1.setValue("郑州市");
        list.add(item1);
        Item item2 =new Item();
        item2.setName("河南省");
        item2.setValue("洛阳市");
        list.add(item2);
        Item item3 =new Item();
        item3.setName("河南省");
        item3.setValue("开封市");
        list.add(item3);
        Item item4 =new Item();
        item4.setName("湖北省");
        item4.setValue("武汉市");
        list.add(item4);
        Item item5 =new Item();
        item5.setName("湖北省");
        item5.setValue("襄阳市");
        list.add(item5);
        Item item6 =new Item();
        item6.setName("湖北省");
        item6.setValue("潜江市");
        list.add(item6);
        Item item7 =new Item();
        item7.setName("湖北省");
        item7.setValue("荆州市");
        list.add(item7);
        Item item8 =new Item();
        item8.setName("北京");
        item8.setValue("北京市");
        list.add(item8);
        return list;
    }
}

 调用结果:

相关文章

  • 前端存token后端获取token代码实例(Spring Boot)

    前端存token后端获取token代码实例(Spring Boot)

    Token其实就是访问资源的凭证,一般是用户通过用户名和密码登录成功之后,服务器将登陆凭证做数字签名,加密之后得到的字符串作为token,这篇文章主要给大家介绍了关于前端存token,Spring Boot后端获取token的相关资料,需要的朋友可以参考下
    2024-07-07
  • SpringBoot:JPA + AuditingEntityListener时区设置方式

    SpringBoot:JPA + AuditingEntityListener时区设置方式

    这篇文章主要介绍了SpringBoot:JPA + AuditingEntityListener时区设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Netty框架实现TCP/IP通信的完美过程

    Netty框架实现TCP/IP通信的完美过程

    这篇文章主要介绍了Netty框架实现TCP/IP通信,这里使用的是Springboot+Netty框架,使用maven搭建项目,需要的朋友可以参考下
    2021-07-07
  • 深入理解Java设计模式之装饰模式

    深入理解Java设计模式之装饰模式

    这篇文章主要介绍了JAVA设计模式之装饰模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2021-11-11
  • spring boot 自定义starter的实现教程

    spring boot 自定义starter的实现教程

    下面小编就为大家分享一篇spring boot 自定义starter的实现教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • Java实现OJ多组测试数据的输入方法

    Java实现OJ多组测试数据的输入方法

    今天小编就为大家分享一篇Java实现OJ多组测试数据的输入方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 解析java中的condition

    解析java中的condition

    Condition 将 Object 监视器方法(wait()、notify()和notifyAll())分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待 set(wait-set)
    2021-06-06
  • java web图片上传和文件上传实例详解

    java web图片上传和文件上传实例详解

    这篇文章主要介绍了java web图片上传和文件上传实例详解的相关资料,这里提供了两种方法及示例代码,需要的朋友可以参考下
    2016-11-11
  • 浅谈java反射和自定义注解的综合应用实例

    浅谈java反射和自定义注解的综合应用实例

    本篇文章主要介绍了java反射和自定义注解的综合应用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • springboot2 生产部署注意事项及示例代码

    springboot2 生产部署注意事项及示例代码

    这篇文章主要介绍了springboot2 生产部署注意事项及示例代码,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04

最新评论