# SpringBoot+Redis 前瞻: Reids的Java客户端有 1.Jedis 2.Lettuce 3.Spring Data Redis 我们主要使用Spring Data Redis ## 1.操作步骤: ### 1.1 导入Spring Data Redis 的maven坐标 ```xml org.springframework.boot spring-boot-starter-data-redis ``` ### 1.2 配置redis数据源 ``` spring: redis: host: ${sky.redis.host} port: ${sky.redis.port} password: ${sky.redis.password} database: ${sky.redis.database} ``` ```yaml sky: redis: host: localhost port: 6379 password: database: 10 ``` ### 1.3 编写配置类,创建RedisTemplete对象 ```java @Configuration @Slf4j public class RedisConfiguration { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){ log.info("创建RedisTemplate对象..."); RedisTemplate redisTemplate = new RedisTemplate(); //设置redis连接工厂对象 redisTemplate.setConnectionFactory(redisConnectionFactory); //设置redis的key的序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); return redisTemplate; } } ``` ![1762315033093](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315033093.png) 加redis的key的序列化器之前: ![1762315212677](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315212677.png) 加redis的key的序列化器之后: ![1762315247579](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315247579.png) ### 1.4 通过Redis Template对象操作Redis ```java @SpringBootTest public class SpringDataRedisTest { @Autowired private RedisTemplate redisTemplate; @Test public void testRedisTemplate(){ System.out.println(redisTemplate); //操作字符串类型 ValueOperations valueOperations = redisTemplate.opsForValue(); HashOperations hashOperations = redisTemplate.opsForHash(); ListOperations listOperations = redisTemplate.opsForList(); SetOperations setOperations = redisTemplate.opsForSet(); ZSetOperations zSetOperations = redisTemplate.opsForZSet(); } //String类型 @Test public void testString(){ //set get setex setnx redisTemplate.opsForValue().set("name","小明"); String city = (String) redisTemplate.opsForValue().get("name"); System.out.println(city); redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES); //setIfAbsent就是setnx redisTemplate.opsForValue().setIfAbsent("lock","1"); redisTemplate.opsForValue().setIfAbsent("lock","2"); } //Hash类型 @Test public void testHash(){ //hset hget hdel hkeys hvals HashOperations hashOperations = redisTemplate.opsForHash(); //hset hashOperations.put("100","name","yinshunyu"); hashOperations.put("100","age","20"); //get String name = (String) hashOperations.get("100", "name"); System.out.println(name); //hkeys Set keys = hashOperations.keys("100"); System.out.println(keys); //hvals List values = hashOperations.values("100"); System.out.println(values); //hdel hashOperations.delete("100","age"); } //List类型 @Test public void testList(){ //lpush lrange rpop llen ListOperations listOperations = redisTemplate.opsForList(); listOperations.leftPushAll("mylist","a","b","c"); listOperations.leftPush("mylist","d"); List mylist = listOperations.range("mylist", 0, -1); System.out.println(mylist); listOperations.rightPop("mylist"); Long size = listOperations.size("mylist"); System.out.println(size); } //Set类型 @Test public void testSet(){ //sadd smembers scard sinter sunion srem SetOperations setOperations = redisTemplate.opsForSet(); setOperations.add("set1","a","b","c","d"); setOperations.add("set2","a","b","x","y"); //smembers 获取元素 Set members = setOperations.members("set1"); System.out.println(members); //scard 元素个数 Long size = setOperations.size("set1"); System.out.println(size); //sinter 交集 Set intersect = setOperations.intersect("set1", "set2"); System.out.println(intersect); //sunion 并集 Set union = setOperations.union("set1", "set2"); System.out.println( union); setOperations.remove("set1","a","b"); } //ZSet类型 @Test public void testZset(){ //zadd zrange zincrby zrem ZSetOperations zSetOperations = redisTemplate.opsForZSet(); zSetOperations.add("zset1","a",10); zSetOperations.add("zset1","b",12); zSetOperations.add("zset1","c",9); Set zset1 = zSetOperations.range("zset1", 0, -1); System.out.println(zset1); //zincrby 修改分数 zSetOperations.incrementScore("zset1","c",10); zSetOperations.remove("zset1","a","b"); } } ``` ![1762315160999](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315160999.png) ## 2.缓存菜品模拟 **修改用户端接口 DishController 的 list 方法,加入缓存处理逻辑:** ```java @Autowired private RedisTemplate redisTemplate; /** * 根据分类id查询菜品 * * @param categoryId * @return */ @GetMapping("/list") @ApiOperation("根据分类id查询菜品") public Result> list(Long categoryId) { //构造redis中的key,规则:dish_分类id String key = "dish_" + categoryId; //查询redis中是否存在菜品数据 List list = (List) redisTemplate.opsForValue().get(key); if(list != null && list.size() > 0){ //如果存在,直接返回,无须查询数据库 return Result.success(list); } //////////////////////////////////////////////////////// Dish dish = new Dish(); dish.setCategoryId(categoryId); dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品 //如果不存在,查询数据库,将查询到的数据放入redis中 list = dishService.listWithFlavor(dish); //////////////////////////////////////////////////////// redisTemplate.opsForValue().set(key, list); return Result.success(list); } ``` **抽取清理缓存的方法:** 在管理端DishController中添加 ```java @Autowired private RedisTemplate redisTemplate; /** * 清理缓存数据 * @param pattern */ private void cleanCache(String pattern){ Set keys = redisTemplate.keys(pattern); redisTemplate.delete(keys); } ``` **调用清理缓存的方法,保证数据一致性:** **1). 新增菜品优化** ```java /** * 新增菜品 * * @param dishDTO * @return */ @PostMapping @ApiOperation("新增菜品") public Result save(@RequestBody DishDTO dishDTO) { log.info("新增菜品:{}", dishDTO); dishService.saveWithFlavor(dishDTO); //清理缓存数据 String key = "dish_" + dishDTO.getCategoryId(); cleanCache(key); return Result.success(); } ``` # EasyExcel初步理解 ## 依赖导入 ``` com.alibaba easyexcel 2.1.1 org.projectlombok lombok 1.18.10 ``` ### 创建与表格对应的实体类 ``` @Data @AllArgsConstructor @NoArgsConstructor public class Student { @ExcelProperty(value = "学生id") private Integer id; @ExcelProperty(value = "学生姓名") private String name; @ExcelProperty(value = "学生年龄") private Integer age; } ``` ## 写操作 ``` public class WriteExcel { public static void main(String[] args) { //准备文件路径 String fileName="D:/destory/test/easyexcel.xls"; //写出文件 EasyExcel.write(fileName, Student.class).sheet("easyexcel") .doWrite(data()); } private static List data(){ ArrayList list = new ArrayList<>(); for (int i = 0; i < 10; i++) { Student student = new Student(i, "董德" + 1, 22 + i); list.add(student); } return list; } } ``` ## 读操作 ### 改造实体类 ``` @Data @AllArgsConstructor @NoArgsConstructor public class Student { @ExcelProperty(value = "学生id",index = 0) private Integer id; @ExcelProperty(value = "学生姓名",index = 1) private String name; @ExcelProperty(value = "学生年龄",index = 2) private Integer age; } ``` ### 创建监听器 ``` public class EasyExcelLinster extends AnalysisEventListener { List list= new ArrayList(); //一行一行的去读取里面的数据 @Override public void invoke(Student student, AnalysisContext analysisContext) { System.out.println(student); list.add(student); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } } ``` ### 读取 ``` public class ReadExcel { public static void main(String[] args) { //准备文件路径 String fileName="D:/destory/test/easyexcel.xls"; EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead(); } } ```