目录
1.2:配置SpringBoot核心配置文件application.properties
二:在Config文件夹中创建RedisConfig配置文件类
应用背景
将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方。 缓存就是一个存储器,在技术选型中,常用 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;
}
}
调用结果: