SpringBoot学习之路(六)Redis流程(自定义)
首先添加依赖
<!-- 业务层缓存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
添加Redis序列化器和反序列化器的配置
@SpringBootConfiguration public class MyRedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); //创建模板类对象 RedisSerializer<String> redisSerializer = new StringRedisSerializer();//创建String序列化类 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //指定使用jackson工具负责具体的序列化操作 ObjectMapper om = new ObjectMapper(); //创建jackson的核心api的 ObjectMapper,将bean,list,map,数组等等转成字符串 om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 使用objectmapper设置bean的属性,修饰符 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //设置默认类型 om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //设置将本地时间转成字符串 jackson2JsonRedisSerializer.setObjectMapper(om); //将核心api objectmapper设置给jackson template.setConnectionFactory(factory); // 通过工厂得到连接对象 template.setKeySerializer(redisSerializer); //设置key序列化方式: 转成字符串 template.setValueSerializer(jackson2JsonRedisSerializer); // 设置value序列化: 字符串 template.setHashValueSerializer(jackson2JsonRedisSerializer); // valuehashmap序列化 return template; } }
添加Redis服务器相关配置
spring: redis: host: localhost port: 6379 lettuce: pool: max-active: 8 min-idle: 3
通过spring框架提供的模板类RedisTemplate调用API操作Redis数据库
@Service public class CatalogServiceImpl extends ServiceImpl<CatalogMapper, Catalog> implements CatalogService { @Autowired private RedisTemplate redisTemplate; private ThreadLocalRandom random = ThreadLocalRandom.current(); @Override public List<Catalog> listByPage(PageBean pages) { List<Catalog> res = new ArrayList<>(); 9.5、使用postman测试,可以在控制台上查看是否有对应的SQL语句输出以判断缓存是否生效 注解开发 注解提供了更声明式和方便的方式,而编码方式允许更精细的控制和定制。 if (pages == null || pages.getRowsPerPage() < 1) { //查询所有,避免缓存穿透,索引允许存储数据为空集 if (redisTemplate.hasKey("catalog::all")) { //如果在具体开发种比较倾向于使用常量的方式 Object obj = redisTemplate.opsForValue().get("catalog::all"); if (obj != null && obj instanceof List) res = (List<Catalog>) obj; } else { res = this.getBaseMapper().selectList(null); //为了避免雪崩问题,所以生存周期引入随机数 int kk = 100 + random.nextInt(100); redisTemplate.opsForValue().set("catalog::all", res, Duration.ofSeconds(kk)); } } else { //分页查询。实际上具体应用中不一定针对分页数据进行缓存 catalog::page::size if (pages.getPageNum() < 1) pages.setPageNum(1); String key = "catalog::" + pages.getPageNum() + "::" + pages.getRowsPerPage(); if (this.redisTemplate.hasKey(key)) { Object obj = redisTemplate.opsForValue().get(key); if (obj != null && obj instanceof List) res = (List<Catalog>) obj; if(this.redisTemplate.hasKey(key+"::page")){ obj = redisTemplate.opsForValue().get(key+"::page"); if (obj != null && obj instanceof PageBean) { PageBean tmp = (PageBean) obj; BeanUtils.copyProperties(tmp,pages); } } } if (res == null || res.size() < 1) { Page<Catalog> pageInfo = new Page<>(pages.getPageNum(), pages.getRowsPerPage()); pageInfo = this.getBaseMapper().selectPage(pageInfo, null); res = pageInfo.getRecords(); pages.setPageNum(pageInfo.getCurrent()); pages.setRowsNum(pageInfo.getTotal()); pages.setMaxPage(pageInfo.getPages()); int kk = 100 + random.nextInt(100); //随机数时长用于避免雪崩 redisTemplate.opsForValue().set(key, res, Duration.ofSeconds(kk)); redisTemplate.opsForValue().set(key+"::page", pages, Duration.ofSeconds(kk)); } } return res; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构