Spring boot - 整合 Redis缓存(下)
在SpringBoot项目中使用Redis进行缓存接口返回数据,以及结合课程表的增删查改进行获取更新缓存。
一、相关注解 @Cacheable、@CachePut、@CacheEvict
在SpringBoot项目中我们进行缓存接口数据主要使用的是Spring的缓存注解 @Cacheable、@CachePut、@CacheEvict
@Cacheable:表示当访问到改方法上首先从缓存中获取,如果缓存中没有则会执行方法内部代码,并将代码返回的数据存在缓存中;
@CachePut:表示每次请求调用该方法后都会执行函数内部代码,将返回数据存放在注解所指定的key中;
@CacheEvict:表示执行函数内部代码后,并将注解所指定的key进行删除;
二、在我们的场景中使用缓存
我们现在需要写一个课程列表查询(根据教师编号),以及课程添加、修改、删除。我们将缓存添加在业务实现类上面
com.demo.serviceImpl.CourseServiceImpl
1,给课程列表查询添加缓存,key为教师编号
/*** 给某个教师的课程列表添加缓存,如果有缓存直接返回缓存结果,没有查询添加缓存*/
@Cacheable(value="redisCache",key="#course.userId")
@Override
public List<Course> getCourList(Course course) {CourseExample example = new CourseExample();CourseExample.Criteria createCriteria = example.createCriteria();String userId = course.getUserId();if(userId!= null && userId!= ""){createCriteria.andUserIdEqualTo(userId);}List<Course> cours = courseDao.selectByExample(example);return cours;
}
@Cacheable中的value表示缓存存储在哪一个redis库中,key使用了SpringEL的表达式#开头。
2,添加课程后,以课程id为缓存key添加缓存,并更新改课程老师的列表缓存 cacheService.updateCourListCache。
/*** 新增课程,并清除该教师下的课程列表缓存*/
@CachePut(value="redisCache",key="#course.courId")
@Override
public int addCourse(Course course) {int insertSelective = courseDao.insertSelective(course);if(insertSelective > 0){cacheService.updateCourListCache(course);}return insertSelective;
}
3,删除课程,并删除课程缓存,更新教师课程列表缓存
/*** 删除课程,删除课程缓存,更新教师课程列表缓存*/
@CacheEvict(value="redisCache",key="#course.courId")
@Override
public int delteCour(Course course) {String courId = course.getCourId();int deleteNum = courseDao.deleteByPrimaryKey(courId );if(deleteNum>0){cacheService.updateCourListCache(course);}return deleteNum;
}
注意:在更新教师课程列表缓存的时候我们没有直接调用该类内部的getCourList方法,因为在同一个类中调用其他缓存方法,被调用方法缓存注解实际是无效的。这时我们需要新写一个接口,在此类中注入该接口实现类,在另一个接口实现类内部去更新缓存。
@Service
public class CacheServiceImpl implements CacheService{@Autowiredprivate CourseDao courseDao;@CachePut(value="redisCache",key="#course.userId")@Overridepublic List<Course> updateCourListCache(Course course) {CourseExample example = new CourseExample();List<Course> cours = courseDao.selectByExample(example);return cours;}
}
同理我们的修改课程,删除课程都会通过注入缓存实现类去更新列表缓存。
三、我们的课程列表前台页面以及主要后台类以及配置文件如下:
├─main
│ ├─java
│ │ └─com
│ │ └─demo
│ │ │ Application.java
│ │ ├─bean
│ │ │ Course.java
│ │ │ CourseExample.java
│ │ │ User.java
│ │ ├─controller
│ │ │ CourController.java
│ │ │ CourseController.java
│ │ │ PageController.java
│ │ │ UserController.java
│ │ ├─dao
│ │ │ CourseDao.java
│ │ │ CourseMapper.xml
│ │ ├─filter
│ │ │ LoginFilter.java
│ │ ├─redis
│ │ │ RedisConfig.java
│ │ │ RedisServiceImpl.java
│ │ ├─service
│ │ │ CacheService.java
│ │ │ CourseService.java
│ │ └─serviceImpl
│ │ CacheServiceImpl.java
│ │ CourseServiceImpl.java
│ └─resources
│ │ application.properties
│ │ mybatis-config.xml
│ ├─static
│ │ index.html
│ └─templates
│ add.html
│ courList.html
│ header.html
│ index.html
└─test├─java└─resources
/bootdemo/src/main/resources/templates/courList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
<style type="text/css">
.odd{background: #ccc;}table{ border-collapse:collapse; }
</style>
</head>
<body>
<a th:href="@{/course/courInput}">新增</a>
<table border="1" ><tr><th>id</th><th>name</th><th>cour_desc</th><th>update</th></tr><tr th:each="cour,courStat : ${courList}" th:class="${courStat.odd}? 'odd'" th:index="${courStat.index}" th:count ="${courStat.count}" th:isFirst="${courStat.first}" th:isLast="${courStat.Last}"><td th:text="${cour.courId}">Onions</td><td th:text="${cour.courName}">Onions</td><td th:text="${cour.courDesc}">Onions</td><td ><a th:href="@{/course/courInput(courId=${cour.courId})}">修改</a><a th:href="@{/course/deleteCour(courId=${cour.courId})}">删除</a></td></tr>
</table>
</body>
</html>
/bootdemo/src/main/resources/templates/add.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
<style type="text/css">
</style>
</head>
<body>
<form method="post" th:action="@{/course/{method}/(method=${course.courId !=null ? 'updateCour':'addCour'})}"><input name="courId" type="hidden" th:value="${course.courId}" /><input name="userId" type="hidden" th:value="${course.userId}" /><table><tr><td>name</td><td><input name="courName" th:value="${course.courName}" /> </td></tr><tr><td>desc</td><td><input name="courDesc" th:value="${course.courDesc}"/> </td></tr><tr><td colspan="2"><button type="submit">提交</button></td></tr></table>
</form>
</body>
</html>
com.demo.controller.CourseController
@Controller
@RequestMapping(value="/course")
public class CourseController {@Autowiredprivate RedisServiceImpl redisService;@Autowiredprivate CourseService courseService;/*** 获取课程列表* @param course* @param mp* @return*/@RequestMapping(value="/getCourList",method=RequestMethod.GET)public String getCourList(Course course,ModelMap mp){List<Course> list = courseService.getCourList(course);mp.put("courList", list);return "courList";}/*** 跳转表单页面,根据课程编号是否为空判断* @param course* @param mp* @return*/@RequestMapping(value="/courInput",method=RequestMethod.GET)public String courAdd(Course course,ModelMap mp){if(course != null && course.getCourId() != null && course.getCourId() != ""){Course course2 = courseService.getCourse(course);mp.put("course", course2);}System.out.println(course);return "add";}/*** 新增课程,放课程详情缓存,更新列表缓存* @param course* @param mp* @return*/@RequestMapping(value="/addCour",method=RequestMethod.POST)public String Addcour(Course course,ModelMap mp){String userId = "t0001";//应该session获取course.setCourId(System.currentTimeMillis()+"");course.setUserId(userId);courseService.addCourse(course);return "redirect:/course/getCourList?userId="+userId;}/*** 放课程详情缓存,更新列表缓存* @param course* @param mp* @return*/@RequestMapping(value="/updateCour",method=RequestMethod.POST)public String updateCour(Course course,ModelMap mp){course.setUserId("t0001");courseService.updateCourse(course);return "redirect:/course/getCourList?userId=t0001";}/*** 课程删除 删除详情缓存,更新列表缓存* @param course* @param mp* @return*/@RequestMapping(value="/deleteCour",method=RequestMethod.GET)public String deleteCour(Course course,ModelMap mp){course.setUserId("t0001");courseService.delteCour(course);return "redirect:/course/getCourList?userId=t0001";}//==================== redisTemplate 测试 =========================@RequestMapping(value="/setCourVal",method=RequestMethod.GET)public void setCourVal(String val){redisService.set("testkey", val);}@ResponseBody@RequestMapping(value="/getCourVal",method=RequestMethod.GET)public String getCourVal(String val){return redisService.get("testkey");}
}
/bootdemo/src/main/java/com/demo/serviceImpl/CourseServiceImpl.java
@Service
public class CourseServiceImpl implements CourseService {@Autowiredprivate CacheService cacheService;@Autowiredprivate CourseDao courseDao;/*** 给某个教师的课程列表添加缓存,如果有缓存直接返回缓存结果,没有查询添加缓存*/@Cacheable(value="redisCache",key="#course.userId")@Overridepublic List<Course> getCourList(Course course) {CourseExample example = new CourseExample();CourseExample.Criteria createCriteria = example.createCriteria();String userId = course.getUserId();if(userId!= null && userId!= ""){createCriteria.andUserIdEqualTo(userId);}List<Course> cours = courseDao.selectByExample(example);return cours;}/*** 新增课程,并清除该教师下的课程列表缓存*/@CachePut(value="redisCache",key="#course.courId")@Overridepublic Course addCourse(Course course) {int insertSelective = courseDao.insertSelective(course);if(insertSelective > 0){cacheService.updateCourListCache(course);return course;}return null;}/*** 删除课程,删除课程缓存,更新教师课程列表缓存*/@CacheEvict(value="redisCache",key="#course.courId")@Overridepublic int delteCour(Course course) {String courId = course.getCourId();int deleteNum = courseDao.deleteByPrimaryKey(courId );if(deleteNum>0){cacheService.updateCourListCache(course);}return deleteNum;}@CacheEvict(value="redisCache",key="#course.courId")@Overridepublic int updateCourse(Course course) {int updateNum = courseDao.updateByPrimaryKeySelective(course);if(updateNum > 0){cacheService.updateCourListCache(course);}return updateNum;}@Cacheable(value="redisCache",key="#course.courId")@Overridepublic Course getCourse(Course course) {return courseDao.selectByPrimaryKey(course.getCourId());}}
com.demo.serviceImpl.CacheServiceImpl
@Service
public class CacheServiceImpl implements CacheService{@Autowiredprivate CourseDao courseDao;@CachePut(value="redisCache",key="#course.userId")@Overridepublic List<Course> updateCourListCache(Course course) {CourseExample example = new CourseExample();List<Course> cours = courseDao.selectByExample(example);return cours;}}
四、测试验证
测试新增,控制台打印如下:
LocalAddr:/WebDemo/course/getCourList
LocalAddr:/WebDemo/course/courInput
com.demo.bean.Course@33e6d4a3
LocalAddr:/WebDemo/course/addCour/
2019-05-25 16:02:09.108 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.insertSelective : ==> Preparing: insert into course ( cour_id, user_id, cour_name, cour_desc ) values ( ?, ?, ?, ? )
2019-05-25 16:02:09.114 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.insertSelective : ==> Parameters: 1558771329097(String), t0001(String), Spring Boot 缓存应用(String), Reids缓存使用的概述(String)
2019-05-25 16:02:09.156 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.insertSelective : <== Updates: 1
2019-05-25 16:02:09.172 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.selectByExample : ==> Preparing: select cour_id, user_id, cour_name, cour_desc, cour_file, cour_file_name, sta_time, end_time, full_score, state, cour_dir_id, cour_create_time from course
2019-05-25 16:02:09.173 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.selectByExample : ==> Parameters:
2019-05-25 16:02:09.182 DEBUG 6624 --- [nio-8080-exec-7] com.demo.dao.CourseDao.selectByExample : <== Total: 14
LocalAddr:/WebDemo/course/getCourList
如上我们可以看到当我们在课程列表页面点击新增后进入新增页面,在输入完成后点击提交在新增课程接口中首先进行了一次数据库新增操作,操作完成后调用列表缓存类去数据库查询使用@CachePut(value="redisCache",key="#course.userId")注解重新查询重置了下列表缓存,所以当我们新增接口调用结束,返回到列表视图的时候,缓存已经更新,此时类别中已经有了我们新增的该课程。
我们在点击修改课程看看控制台打印:
LocalAddr:/WebDemo/course/courInput
com.demo.bean.Course@3efb9a80
提交
LocalAddr:/WebDemo/course/updateCour/
2019-05-25 16:34:21.805 DEBUG 3364 --- [nio-8080-exec-6] c.d.d.C.updateByPrimaryKeySelective : ==> Preparing: update course SET user_id = ?, cour_name = ?, cour_desc = ? where cour_id = ?
2019-05-25 16:34:21.893 DEBUG 3364 --- [nio-8080-exec-6] c.d.d.C.updateByPrimaryKeySelective : ==> Parameters: t0001(String), Spring Boot 缓存应用2(String), Reids缓存使用的概述2(String), 1558771329097(String)
2019-05-25 16:34:21.964 DEBUG 3364 --- [nio-8080-exec-6] c.d.d.C.updateByPrimaryKeySelective : <== Updates: 1
2019-05-25 16:34:22.013 DEBUG 3364 --- [nio-8080-exec-6] com.demo.dao.CourseDao.selectByExample : ==> Preparing: select cour_id, user_id, cour_name, cour_desc, cour_file, cour_file_name, sta_time, end_time, full_score, state, cour_dir_id, cour_create_time from course
2019-05-25 16:34:22.014 DEBUG 3364 --- [nio-8080-exec-6] com.demo.dao.CourseDao.selectByExample : ==> Parameters:
2019-05-25 16:34:22.091 DEBUG 3364 --- [nio-8080-exec-6] com.demo.dao.CourseDao.selectByExample : <== Total: 14
LocalAddr:/WebDemo/course/getCourList
同样他回现在数据库做一个更新操作,并将列表缓存也进行刷新一次。
SpringBoot缓存配置上部分,请查看此博文 https://blog.csdn.net/liuhenghui5201/article/details/90544737
项目代码变更记录:
https://github.com/liuhenghui/SpringBootDemo/commit/a6504131d337e25d89fe2765cd69f4672d47351c
https://github.com/liuhenghui/SpringBootDemo/commit/fecd3d1eee47cb61b00881038d15ca9b91eb298f
Spring boot - 整合 Redis缓存(下)相关推荐
- Spring boot - 整合 Redis缓存(上)
一.配置Pom文件 在使用spring boot 2.0整合redis时遇到了好多问题,网上很多例子都是1.x版本的.故2.0没有折腾好所以将2.0降到了1.5.降级后由于thymeleaf版本也会从 ...
- Spring Boot基础学习笔记18:Spring Boot整合Redis缓存实现
文章目录 零.学习目标 一.Spring Boot支持的缓存组件 二.基于注解的Redis缓存实现 (一)安装与启动Redis (二)创建Spring Boot项目 - RedisCacheDemo0 ...
- Spring Boot整合Redis缓存(Lettuce)
spring-boot-demo-cache-redis 此 demo 主要演示了 Spring Boot 如何整合 redis,操作redis中的数据,并使用redis缓存数据.连接池使用 Lett ...
- 猿创征文 | 微服务 Spring Boot 整合Redis 实战开发解决高并发数据缓存
文章目录 一.什么是 缓存? ⛅为什么用缓存? ⚡如何使用缓存 二.实现一个商家缓存 ⌛环境搭建 ♨️核心源码 ✅测试接口 三.采用 微服务 Spring Boot 注解开启缓存 ✂️@CacheEn ...
- Spring boot整合Redis(入门教程)
目录 源码分析 jedis VS lettuce 整合测试 导入依赖 配置连接 测试 存入字符串 存入对象 五大数据类型操作 自定义RedisConfig 存入对象 Redis工具类(常用API) 以 ...
- 大聪明教你学Java | Spring Boot 整合 Redis 实现访问量统计
前言 之前开发系统的时候客户提到了一个需求:需要统计某些页面的访问量,记得当时还纠结了一阵子,不知道怎么去实现这个功能,后来还是在大佬的带领下借助 Redis 实现了这个功能.今天又回想起了这件事,正 ...
- Spring Boot整合Redis以及Redis的原理
Redis的原理及知识 Redis简介 redis是一个key-value.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...
- Spring Boot集成Redis缓存之模拟高并发场景处理
前言 同样我们以上一篇文章为例子,搭建好环境之后,我欧美可以模拟高并发场景下,我们的缓存效率怎么样,到底能不能解决我们实际项目中的缓存问题.也就是如何解决缓存穿透? Spring Boot集成Redi ...
- 十一、Spring Boot整合Redis(一)
Spring Boot整合Redis 1. SpringBoot+单例Redis 1)引入依赖 <dependency> <groupId>org.springf ...
最新文章
- visual studio 2010 professional , premium, ultimate各版本功能对比
- 在CentOS7上配置Open vSwitch和VXLAN
- bzoj 3195 奇怪的道路
- linux命令中提取某一列,怎么用Linux命令提取表格文本中的某列
- 聊聊传说中的散列哈希Hash算法,以及Java中的HashTable,HashMap,HashSet,ConcurrentHashMap......
- Canvas开发库封装
- flex发布的release程序要配release的Flash Player,速度飞快!如果有一方是debug版本的,速度就降下来了,要注意!...
- mongodb 的基本函数语法封装
- 如何在XML序列化时隐藏可为null的的字段(XmlElement和XmlAttribute)
- ups维护服务器,UPS电源的在线维护和管理
- 横向对比EXT4,带你感受真实的Linux文件系统F2FS
- 自己小米4c 高通9008模式刷机 低版本 亲测有效
- TOOLFK工具-在线二维码解码工具
- 血浆/血清RNA提取试剂盒的功能和特色
- 怎么把几个视频合并成一个?学会这个技巧,轻松掌握
- linux swift开发环境,Linux平台swift语言开发学习环境搭建
- win10系统C盘存储使用优化操作教程
- 07【Listener、Ajax、Json】
- 《设计模式之禅》观后感-六大设计原则(一)
- 小昭的早晨——微信小程序开发伊始