提交学习笔记专用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
9.7 KiB

  1. # SpringBoot+Redis
  2. 前瞻:
  3. Reids的Java客户端有
  4. 1.Jedis
  5. 2.Lettuce
  6. 3.Spring Data Redis
  7. 我们主要使用Spring Data Redis
  8. ## 1.操作步骤:
  9. ### 1.1 导入Spring Data Redis 的maven坐标
  10. ```xml
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-data-redis</artifactId>
  14. </dependency>
  15. ```
  16. ### 1.2 配置redis数据源
  17. ```
  18. spring:
  19. redis:
  20. host: ${sky.redis.host}
  21. port: ${sky.redis.port}
  22. password: ${sky.redis.password}
  23. database: ${sky.redis.database}
  24. ```
  25. ```yaml
  26. sky:
  27. redis:
  28. host: localhost
  29. port: 6379
  30. password:
  31. database: 10
  32. ```
  33. ### 1.3 编写配置类,创建RedisTemplete对象
  34. ```java
  35. @Configuration
  36. @Slf4j
  37. public class RedisConfiguration {
  38. @Bean
  39. public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
  40. log.info("创建RedisTemplate对象...");
  41. RedisTemplate redisTemplate = new RedisTemplate();
  42. //设置redis连接工厂对象
  43. redisTemplate.setConnectionFactory(redisConnectionFactory);
  44. //设置redis的key的序列化器
  45. redisTemplate.setKeySerializer(new StringRedisSerializer());
  46. return redisTemplate;
  47. }
  48. }
  49. ```
  50. ![1762315033093](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315033093.png)
  51. 加redis的key的序列化器之前:
  52. ![1762315212677](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315212677.png)
  53. 加redis的key的序列化器之后:
  54. ![1762315247579](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315247579.png)
  55. ### 1.4 通过Redis Template对象操作Redis
  56. ```java
  57. @SpringBootTest
  58. public class SpringDataRedisTest {
  59. @Autowired
  60. private RedisTemplate redisTemplate;
  61. @Test
  62. public void testRedisTemplate(){
  63. System.out.println(redisTemplate);
  64. //操作字符串类型
  65. ValueOperations valueOperations = redisTemplate.opsForValue();
  66. HashOperations hashOperations = redisTemplate.opsForHash();
  67. ListOperations listOperations = redisTemplate.opsForList();
  68. SetOperations setOperations = redisTemplate.opsForSet();
  69. ZSetOperations zSetOperations = redisTemplate.opsForZSet();
  70. }
  71. //String类型
  72. @Test
  73. public void testString(){
  74. //set get setex setnx
  75. redisTemplate.opsForValue().set("name","小明");
  76. String city = (String) redisTemplate.opsForValue().get("name");
  77. System.out.println(city);
  78. redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
  79. //setIfAbsent就是setnx
  80. redisTemplate.opsForValue().setIfAbsent("lock","1");
  81. redisTemplate.opsForValue().setIfAbsent("lock","2");
  82. }
  83. //Hash类型
  84. @Test
  85. public void testHash(){
  86. //hset hget hdel hkeys hvals
  87. HashOperations hashOperations = redisTemplate.opsForHash();
  88. //hset
  89. hashOperations.put("100","name","yinshunyu");
  90. hashOperations.put("100","age","20");
  91. //get
  92. String name = (String) hashOperations.get("100", "name");
  93. System.out.println(name);
  94. //hkeys
  95. Set keys = hashOperations.keys("100");
  96. System.out.println(keys);
  97. //hvals
  98. List values = hashOperations.values("100");
  99. System.out.println(values);
  100. //hdel
  101. hashOperations.delete("100","age");
  102. }
  103. //List类型
  104. @Test
  105. public void testList(){
  106. //lpush lrange rpop llen
  107. ListOperations listOperations = redisTemplate.opsForList();
  108. listOperations.leftPushAll("mylist","a","b","c");
  109. listOperations.leftPush("mylist","d");
  110. List mylist = listOperations.range("mylist", 0, -1);
  111. System.out.println(mylist);
  112. listOperations.rightPop("mylist");
  113. Long size = listOperations.size("mylist");
  114. System.out.println(size);
  115. }
  116. //Set类型
  117. @Test
  118. public void testSet(){
  119. //sadd smembers scard sinter sunion srem
  120. SetOperations setOperations = redisTemplate.opsForSet();
  121. setOperations.add("set1","a","b","c","d");
  122. setOperations.add("set2","a","b","x","y");
  123. //smembers 获取元素
  124. Set members = setOperations.members("set1");
  125. System.out.println(members);
  126. //scard 元素个数
  127. Long size = setOperations.size("set1");
  128. System.out.println(size);
  129. //sinter 交集
  130. Set intersect = setOperations.intersect("set1", "set2");
  131. System.out.println(intersect);
  132. //sunion 并集
  133. Set union = setOperations.union("set1", "set2");
  134. System.out.println( union);
  135. setOperations.remove("set1","a","b");
  136. }
  137. //ZSet类型
  138. @Test
  139. public void testZset(){
  140. //zadd zrange zincrby zrem
  141. ZSetOperations zSetOperations = redisTemplate.opsForZSet();
  142. zSetOperations.add("zset1","a",10);
  143. zSetOperations.add("zset1","b",12);
  144. zSetOperations.add("zset1","c",9);
  145. Set zset1 = zSetOperations.range("zset1", 0, -1);
  146. System.out.println(zset1);
  147. //zincrby 修改分数
  148. zSetOperations.incrementScore("zset1","c",10);
  149. zSetOperations.remove("zset1","a","b");
  150. }
  151. }
  152. ```
  153. ![1762315160999](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315160999.png)
  154. ## 2.缓存菜品模拟
  155. **修改用户端接口 DishController 的 list 方法,加入缓存处理逻辑:**
  156. ```java
  157. @Autowired
  158. private RedisTemplate redisTemplate;
  159. /**
  160. * 根据分类id查询菜品
  161. *
  162. * @param categoryId
  163. * @return
  164. */
  165. @GetMapping("/list")
  166. @ApiOperation("根据分类id查询菜品")
  167. public Result<List<DishVO>> list(Long categoryId) {
  168. //构造redis中的key,规则:dish_分类id
  169. String key = "dish_" + categoryId;
  170. //查询redis中是否存在菜品数据
  171. List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
  172. if(list != null && list.size() > 0){
  173. //如果存在,直接返回,无须查询数据库
  174. return Result.success(list);
  175. }
  176. ////////////////////////////////////////////////////////
  177. Dish dish = new Dish();
  178. dish.setCategoryId(categoryId);
  179. dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
  180. //如果不存在,查询数据库,将查询到的数据放入redis中
  181. list = dishService.listWithFlavor(dish);
  182. ////////////////////////////////////////////////////////
  183. redisTemplate.opsForValue().set(key, list);
  184. return Result.success(list);
  185. }
  186. ```
  187. **抽取清理缓存的方法:**
  188. 在管理端DishController中添加
  189. ```java
  190. @Autowired
  191. private RedisTemplate redisTemplate;
  192. /**
  193. * 清理缓存数据
  194. * @param pattern
  195. */
  196. private void cleanCache(String pattern){
  197. Set keys = redisTemplate.keys(pattern);
  198. redisTemplate.delete(keys);
  199. }
  200. ```
  201. **调用清理缓存的方法,保证数据一致性:**
  202. **1). 新增菜品优化**
  203. ```java
  204. /**
  205. * 新增菜品
  206. *
  207. * @param dishDTO
  208. * @return
  209. */
  210. @PostMapping
  211. @ApiOperation("新增菜品")
  212. public Result save(@RequestBody DishDTO dishDTO) {
  213. log.info("新增菜品:{}", dishDTO);
  214. dishService.saveWithFlavor(dishDTO);
  215. //清理缓存数据
  216. String key = "dish_" + dishDTO.getCategoryId();
  217. cleanCache(key);
  218. return Result.success();
  219. }
  220. ```
  221. # EasyExcel初步理解
  222. ## 依赖导入
  223. ```
  224. <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
  225. <dependency>
  226. <groupId>com.alibaba</groupId>
  227. <artifactId>easyexcel</artifactId>
  228. <version>2.1.1</version>
  229. </dependency>
  230. <dependency>
  231. <groupId>org.projectlombok</groupId>
  232. <artifactId>lombok</artifactId>
  233. <version>1.18.10</version>
  234. ```
  235. ### 创建与表格对应的实体类
  236. ```
  237. @Data
  238. @AllArgsConstructor
  239. @NoArgsConstructor
  240. public class Student {
  241. @ExcelProperty(value = "学生id")
  242. private Integer id;
  243. @ExcelProperty(value = "学生姓名")
  244. private String name;
  245. @ExcelProperty(value = "学生年龄")
  246. private Integer age;
  247. }
  248. ```
  249. ## 写操作
  250. ```
  251. public class WriteExcel {
  252. public static void main(String[] args) {
  253. //准备文件路径
  254. String fileName="D:/destory/test/easyexcel.xls";
  255. //写出文件
  256. EasyExcel.write(fileName, Student.class).sheet("easyexcel")
  257. .doWrite(data());
  258. }
  259. private static List<Student> data(){
  260. ArrayList<Student> list = new ArrayList<>();
  261. for (int i = 0; i < 10; i++) {
  262. Student student = new Student(i, "董德" + 1, 22 + i);
  263. list.add(student);
  264. }
  265. return list;
  266. }
  267. }
  268. ```
  269. ## 读操作
  270. ### 改造实体类
  271. ```
  272. @Data
  273. @AllArgsConstructor
  274. @NoArgsConstructor
  275. public class Student {
  276. @ExcelProperty(value = "学生id",index = 0)
  277. private Integer id;
  278. @ExcelProperty(value = "学生姓名",index = 1)
  279. private String name;
  280. @ExcelProperty(value = "学生年龄",index = 2)
  281. private Integer age;
  282. }
  283. ```
  284. ### 创建监听器
  285. ```
  286. public class EasyExcelLinster extends AnalysisEventListener<Student> {
  287. List<Student> list= new ArrayList<Student>();
  288. //一行一行的去读取里面的数据
  289. @Override
  290. public void invoke(Student student, AnalysisContext analysisContext) {
  291. System.out.println(student);
  292. list.add(student);
  293. }
  294. @Override
  295. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  296. }
  297. }
  298. ```
  299. ### 读取
  300. ```
  301. public class ReadExcel {
  302. public static void main(String[] args) {
  303. //准备文件路径
  304. String fileName="D:/destory/test/easyexcel.xls";
  305. EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead();
  306. }
  307. }
  308. ```