当前位置: 首页 > 图灵资讯 > 技术篇> 缓存优化

缓存优化

来源:图灵教育
时间:2023-06-26 15:42:44

前言:

经过前面linux,redis,git的学习介绍,我们至此进入项目优化阶段

1.项目问题1-1

用户数量多,系统访问量大

频繁访问数据库,系统性能下降,用户体验差

缓存优化_验证码

2.环境搭建1-2将我们的项目推送远程仓库1-2

缓存优化_redis_02

在创建一个新的分支,在次分支上进行项目优化

缓存优化_验证码_03

缓存优化_验证码_04

将v1.0分支也推送远程仓库

缓存优化_验证码_05

缓存优化_缓存_06

2.1maven坐标1-3

在项目的pom.xml文件中导入springdataredis的maven坐标:

pom.xml

 <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

在项目的application.yml中加入redis相关配置:

application.yml

spring:   redis:    host: localhost    port: 6379    #password: 123456    database: 0 #操作的是0号数据库

redis序列化器RedisConfig1-3

package com.itheima.reggie.config;import org.springframework.cache.annotation.CachingConfigurerSupport;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.RedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;//redis序列化器   1-3@Configurationpublic class RedisConfig extends CachingConfigurerSupport {    @Bean    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();        //默认的Key序列化器为:JdkSerializationRedisSerializer        redisTemplate.setKeySerializer(new StringRedisSerializer());        redisTemplate.setConnectionFactory(connectionFactory);        return redisTemplate;    }}

接着添加,提交

缓存优化_验证码_07

缓存优化_spring cache_08

推送成功

缓存优化_验证码_09

3.缓存短信验证码1-43.1实现思路

前面我们已经实现了移动端手机验证码登录,随机生成的验证码我们是保存在HttpSession中的。现在需要改造为将验证码缓存在Redis中,具体的实现思路如下:

1、在服务端UserController中注入RedisTemplate对象,用于操作Redis

2、在服务端UserController的sendMsg方法中,将随机生成的验证码缓存到Redis中,并设置有效期为5分钟

3、在服务端UserController的login方法中,从Redis中获取缓存的验证码,如果登录成功则删除Redis中的验证码

3.2代码改造1-4UserController

//注入redisTemplate对象    优化1-4    @Autowired    private RedisTemplate redisTemplate;

获取手机验证码优化sendMsg优1-4

//获取手机验证码  优化1-4    @PostMapping("/sendMsg")    public R<String> sendMsg(@RequestBody User user,HttpSession session){        //获取手机号        String phone = user.getPhone();        if(StringUtils.isNotEmpty(phone)){//手机号不为空            //生成随机的4为验证码            String code = ValidateCodeUtils.generateValidateCode(4).toString();            log.info("code={}",code);            //调用阿里云提供的短信服务AP完成发送短信            //SMSUtils.sendMessage("瑞吉外卖","",phone,code);            //需要将验证码保存到session            //session.setAttribute(phone,code);            //将生成的验证码缓存到Redis中,并且设置有效期为5分钟    优1-4            redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);            return R.success("手机验证码发送成功");        }        return R.error("短信发送失败");    }

移动端用户登录优化login优1-4

/**     * 移动端用户登录 优化   优1-4     * @param map     * @param session     * @return     */    @PostMapping("/login")    public R<User> login(@RequestBody Map map, HttpSession session){        log.info(map.toString());        //获取手机号        String phone = map.get("phone").toString();        //获取验证码        String code = map.get("code").toString();        //从Session中获取保存的验证码        //Object codeInSession = session.getAttribute(phone);        //从redis中获取缓存的验证码  优1-4        Object codeInSession = redisTemplate.opsForValue().get(phone);        //进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)        if(codeInSession != null && codeInSession.equals(code)){            //如果能够比对成功,说明登录成功            //判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();            //构造查询条件,将手机号作为查询条件            queryWrapper.eq(User::getPhone,phone);            User user = userService.getOne(queryWrapper);            if(user == null){                //是新用户就自动完成注册                user = new User();                user.setPhone(phone);                user.setStatus(1);                userService.save(user);            }            //将用户id放入session            session.setAttribute("user",user.getId());            //如果用户登录成功,删除Redis中缓存的验证码   优1-4            redisTemplate.delete(phone);            return R.success(user);        }        return R.error("登录失败");    }

3.3测试1-4

运行程序

缓存优化_spring cache_10

查看redis

缓存优化_spring cache_11

登录成功

缓存优化_验证码_12

再次查看redis

缓存优化_redis_13

ps还可以使用redis图形化界面

E:\java\tools\Redis\ziliao\redisclient-win32.x86_64.2.0.jar:Redis图形界面客户端

执行方式:在这个文件所在的目录cmd,执行java-jarredisclient-win32.x86_64.2.0.jar

缓存优化_redis_14

启动成功后,点击左上角的Server---add

缓存优化_redis_15

缓存优化_缓存_16

发送验证码,redis里出现手机号

缓存优化_缓存_17

登录成功后手机号被删除

缓存优化_缓存_18

4.缓存菜品数据1-54.1实现思路1-5

前面我们已经实现了移动端菜品查看功能T对应的服务端方法为DishController的list方法,此方法会根据前端提交的查询条件进行数据库查询操作。在高并发的情况下,频繁查询数据库会导致系统性能下降,服务端响应时间增长。现在需要对此方法进行缓存优化,提高系统的性能。具体的实现思路如下:

1、改造DishController的list方法,先从Redis中获取菜品数据,如果有则直接返回,无需查询数据库;如果没有则查询数据库,并将查询到的菜品数据放入Redis。

2、改造DishController的save和update方法,加入清理缓存的逻辑

缓存优化_spring cache_19

4.2代码实现1-6DishController

//注入redisTemplate对象    优化1-6    @Autowired    private RedisTemplate redisTemplate;

根据菜品分类的id查询菜品改造优化list

//根据菜品分类的id查询菜品改造  优化  优1-6    @GetMapping("/list")    public R<List<DishDto>> list(Dish dish){        List<DishDto> dishDtoList = null;        //动态构造key,使用分类的id和售卖状态可以保证唯一性        //dish_1397844391040167938_1        String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();        //先从redis中获取缓存数据        dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);        if(dishDtoList != null){            //如果存在,直接返回,无需查询数据库            return R.success(dishDtoList);        }        //构造查询条件对象        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());        //添加条件,查询状态为1的也就是起售的菜品        queryWrapper.eq(Dish::getStatus,1);        //添加排序条件        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);        List<Dish> list = dishService.list(queryWrapper);        //遍历list集合        dishDtoList = list.stream().map((item)->{            DishDto dishDto = new DishDto();            //将普通数据赋值进dishDto            BeanUtils.copyProperties(item,dishDto);            //设置菜品分类名            Long categoryId = item.getCategoryId();//分类id            //根据id查询分类对象            Category category = categoryService.getById(categoryId);            if(category != null){                String categoryName = category.getName();                dishDto.setCategoryName(categoryName);            }            //设置菜品口味            Long id = item.getId();            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId,id);            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorLambdaQueryWrapper);            dishDto.setFlavors(dishFlavorList);            return dishDto;        }).collect(Collectors.toList());        //如果不存在,需要查询数据库,将查询到的菜品数据缓存到Redis        //这里解释opsForValue不是村String类型的嘛,为啥可以存list        //opsForValue()是操作String类型数据的方法,但是可以通过一些转        //换操作,将List类型的元素转换为字符串进行存储,比如序列化操作或转换为JSON格式再存储。        //在读取时,我们也需要将其转换为List类型,但是在读取时需要进行一些转换操作,        // 并且这种方式不能很好地支持对List中的元素进行增删改查等操作。因此,在某些情况下,        // 建议使用Redis中专门的List数据结构来存储List类型的数据,以获得更好的性能和支持更多的操作方式。        redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);        return R.success(dishDtoList);    }

4.2.1测试1-6

运行登录,果然在redis中发现了菜品缓存

缓存优化_redis_20

4.3更改save和update1-7修改菜品优化update1-7

更新菜品我们采取,删除redis中所有以dish_开头的key方法,简单粗暴

//修改菜品 优化  优1-7    @PutMapping    public R<String> update(@RequestBody DishDto dishDto){        log.info(dishDto.toString());        //调用我们自己实现的方法因为DishDto中包含了dish_flavor表        dishService.updateWithFlavor(dishDto);        //清理所有的菜品的缓存数据        Set keys = redisTemplate.keys("dish_*");        redisTemplate.delete(keys);        return R.success("新增菜品成功");    }

测试更新菜品,发现更新前菜品缓存还在,更新某一个菜品后,所有的菜品缓存被删除

缓存优化_redis_21

缓存优化_验证码_22

我们再采用精确处理的方法,指清理某个特定被更新的菜品缓存

//修改菜品 优化  优1-7    @PutMapping    public R<String> update(@RequestBody DishDto dishDto){        log.info(dishDto.toString());        //调用我们自己实现的方法因为DishDto中包含了dish_flavor表        dishService.updateWithFlavor(dishDto);        //清理所有的菜品的缓存数据   y1-7//        Set keys = redisTemplate.keys("dish_*");//        redisTemplate.delete(keys);        //清理某个分类下面的菜品缓存数据   y1-7        //思路就在于我们需要知道被更新菜品缓存的key是多少        String key = "dish_" + dishDto.getCategoryId() + "_1";        redisTemplate.delete(key);        return R.success("新增菜品成功");    }

再更新前缓存优4条,更新后剩下3条,说明我们只删除了被更新菜品的缓存

缓存优化_验证码_23

缓存优化_spring cache_24

新增菜品save优化y1-7

/**     * 新增菜品 优化  y1-7     * @param dishDto     * @return     */    @PostMapping    public R save(@RequestBody DishDto dishDto){        log.info(dishDto.toString());        //调用我们自己在DishServiceImpl实现的方法   4-11        //我们在DishServiceImpl业务层中自己实现数据保存(因为涉及两张        // 表操作框架无法为我们提供合适的方法)        dishService.saveWithFlavor(dishDto);        //清理所有的菜品的缓存数据   y1-7//        Set keys = redisTemplate.keys("dish_*");//        redisTemplate.delete(keys);        //清理某个分类下面的菜品缓存数据   y1-7        //思路就在于我们需要知道被更新菜品缓存的key是多少        String key = "dish_" + dishDto.getCategoryId() + "_1";        redisTemplate.delete(key);        return R.success("新增菜品成功");    }

和更新菜品一样的套路,新增前3条,新增后2条

缓存优化_redis_25

缓存优化_redis_26

4.4提交远程并合并主分支1-8提交

缓存优化_spring cache_27

缓存优化_spring cache_28

合并

切回主分支

缓存优化_验证码_29

点击右下角master

缓存优化_spring cache_30

查看代码合并成功,因为出现了我们注释的代码

缓存优化_redis_31

5.SpringCache1-95.1springcache介绍1-9

SpringCache是一个框架,实现了基于注解的缓存功能,只需要简单地加一-个注解,就能实现缓存功能。

SpringCache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。

CacheManager是Spring提供的各种缓存技术抽象接口。

针对不同的缓存技术需要实现不同的CacheManager:

缓存优化_验证码_32

5.2springcahche常用注解y1-9

缓存优化_redis_33

在springboot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类.上使用@EnableCaching开启缓存支持即可。

例如,使用Redis作为缓存技术,只需要导入SpringdataRedis的maven坐标即可。

5.3springcache使用方法y1-10

项目在E:\java学习\瑞吉外卖\course2\cache_demo

新建数据库

缓存优化_spring cache_34

缓存优化_验证码_35

缓存优化_redis_36

pom.xml

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.4.5</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.itheima</groupId>    <artifactId>cache_demo</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>            <scope>compile</scope>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.18.20</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.76</version>        </dependency>        <dependency>            <groupId>commons-lang</groupId>            <artifactId>commons-lang</artifactId>            <version>2.6</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-cache</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-redis</artifactId>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <scope>runtime</scope>        </dependency>        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>mybatis-plus-boot-starter</artifactId>            <version>3.4.2</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>1.1.23</version>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <version>2.4.5</version>            </plugin>        </plugins>    </build></project>

applicationg.yml

server:  port: 8080spring:  application:    #应用的名称,可选    name: cache_demo  datasource:    druid:      driver-class-name: com.mysql.cj.jdbc.Driver      url: jdbc:mysql://localhost:3306/cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true      username: root      password: lzlmybatis-plus:  configuration:    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射    map-underscore-to-camel-case: true    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  global-config:    db-config:      id-type: ASSIGN_ID

实体类User

package com.itheima.entity;import lombok.Data;import java.io.Serializable;@Datapublic class User implements Serializable {    private static final long serialVersionUID = 1L;    private Long id;    private String name;    private int age;    private String address;}

持久层接口UserMapper

package com.itheima.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.itheima.entity.User;import org.apache.ibatis.annotations.Mapper;@Mapperpublic interface UserMapper extends BaseMapper<User>{}

业务层接口UserService

package com.itheima.service;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.entity.User;public interface UserService extends IService<User> {}

业务层接口实现类UserServiceImpl

package com.itheima.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.entity.User;import com.itheima.mapper.UserMapper;import com.itheima.service.UserService;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {}

启动类CacheDemoApplication

package com.itheima;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;@Slf4j@SpringBootApplication@EnableCaching  //开启缓存注解的功能  y1-10public class CacheDemoApplication {    public static void main(String[] args) {        SpringApplication.run(CacheDemoApplication.class,args);        log.info("项目启动成功...");    }}

控制层UserController

package com.itheima.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.itheima.entity.User;import com.itheima.service.UserService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;//y1-10@RestController@RequestMapping("/user")@Slf4jpublic class UserController {    @Autowired    private CacheManager cacheManager;    @Autowired    private UserService userService;}

5.3.1保存方法CachePut:将方法返回值放入缓存y1-10

/**     * CachePut:将方法返回值放入缓存   y1-10     * value:缓存的名称,每个缓存名称下面可以有多个key     * key:缓存的key     */    @CachePut(value = "userCache",key = "#user.id")    @PostMapping    public User save(User user){        userService.save(user);        return user;    }

使用postman进行测试

缓存优化_redis_37

数据库插入数据成功

缓存优化_redis_38

通过debug查看缓存数据查看缓存成功

缓存优化_缓存_39

5.3.2删除方法CacheEvict:清理指定缓存y1-11

/**     * CacheEvict:清理指定缓存   y1-11     * value:缓存的名称,每个缓存名称下面可以有多个key     * key:缓存的key     */    @CacheEvict(value = "userCache",key = "#p0")    //@CacheEvict(value = "userCache",key = "#root.args[0]")    //@CacheEvict(value = "userCache",key = "#id")    @DeleteMapping("/{id}")    public void delete(@PathVariable Long id){        userService.removeById(id);    }

测试

现在缓存中存入a,b

缓存优化_缓存_40

缓存优化_spring cache_41

现在删除a的缓存,但是我们在操作之前先存入c的缓存,以便区分

缓存中只剩b了,成功

缓存优化_redis_42

5.3.3更新方法CacheEvict:清理指定缓存y1-11

//更新方法  CacheEvict:清理指定缓存   y1-11    //@CacheEvict(value = "userCache",key = "#p0.id")    //@CacheEvict(value = "userCache",key = "#user.id")    //@CacheEvict(value = "userCache",key = "#root.args[0].id")    @CacheEvict(value = "userCache",key = "#result.id")    @PutMapping    public User update(User user){        userService.updateById(user);        return user;    }

测试,我们往缓存中加入d,e,f

缓存优化_redis_43

缓存优化_spring cache_44

指定修改d

缓存优化_redis_45

数据库更新成功

缓存优化_验证码_46

查看缓存,再没更新之前时三条数据,执行之后剩下两条d缓存被删除

缓存优化_验证码_47

缓存优化_redis_48

5.3.4查询方法Cacheabley1-12

Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中

/**     * Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓     * 存数据;若没有数据,调用方法并将方法返回值放到缓存中     * value:缓存的名称,每个缓存名称下面可以有多个key     * key:缓存的key     * condition:条件,满足条件时才缓存数据     * unless:满足条件则不缓存     */        //这里解释condition = "#result != null",当返回值不为空时才缓存数据,这是为了防止,我们查不到数据    //也被缓存产生垃圾数据的现象    //unless = "#result == null"时当返回值为空时就不缓存,他和condition是正好相反    //@Cacheable(value = "userCache",key = "#id",condition = "#result != null")    @Cacheable(value = "userCache",key = "#id",unless = "#result == null")    @GetMapping("/{id}")    public User getById(@PathVariable Long id){        User user = userService.getById(id);        return user;    }

测试

缓存优化_redis_49

第一次查询了数据库,因为缓存中没有数据

缓存优化_redis_50

第二次再次查询,不走数据库了,直接走了缓存,因为缓存中有了数据

缓存优化_缓存_51

和上述查询一样的原理,不做测试了

//条件查询,如果id不为空就根据id查,如果name不为空就根据name查,都不为空就一起查    y1-12    @Cacheable(value = "userCache",key = "#user.id + '_' + #user.name")    @GetMapping("/list")    public List<User> list(User user){        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(user.getId() != null,User::getId,user.getId());        queryWrapper.eq(user.getName() != null,User::getName,user.getName());        List<User> list = userService.list(queryWrapper);        return list;    }

5.4使用redis缓存y1-13

缓存优化_redis_52

pom.xml

<dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-cache</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-redis</artifactId>        </dependency>

application.yml

缓存优化_redis_53

server:  port: 8080spring:  application:    #应用的名称,可选    name: cache_demo  datasource:    druid:      driver-class-name: com.mysql.cj.jdbc.Driver      url: jdbc:mysql://localhost:3306/cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true      username: root      password: lzl  #加入redis   y1-13  redis:    host: localhost    port: 6379    #password: 123456    #操作的是0号数据库    database: 0  cache:    redis:      time-to-live: 1800000 #设置缓存数据的过期时间mybatis-plus:  configuration:    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射    map-underscore-to-camel-case: true    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  global-config:    db-config:      id-type: ASSIGN_ID

测试查询方法

@Cacheable(value = "userCache",key = "#id",unless = "#result == null")    @GetMapping("/{id}")    public User getById(@PathVariable Long id){        User user = userService.getById(id);        return user;    }

测试缓存成功

缓存优化_验证码_54

6.缓存套餐数据y1-146.1实现思路

前面我们已经实现了移动端套餐查看功能,对应的服务端方法为SetmealController的list方法,此方法会根据前端提交的查询条件进行数据库查询操作。在高并发的情况下,频繁查询数据库会导致系统性能下降,服务端响应时间增长。现在需要对此方法进行缓存优化,提高系统的性能。

具体的实现思路如下:

1、导入SpringCache和Redis相关maven坐标.

2、在application.yml中配置缓存数据的过期时间

3、在启动类上加入@EnableCaching注解,开启缓存注解功能

4、在SetmealController的list方法上加入@Cacheable注解

5、在SetmealController的save和delete方法.上加入CacheEvict注解

6.2代码实现y1-14导入SpringCache和Redis相关maven坐标.pom.xml

<!--redis依赖   y1-3--><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--spring cache依赖  y1-14--><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-cache</artifactId></dependency>

在application.yml中配置缓存数据的过期时间y1-14

缓存优化_spring cache_55

application.yml

cache:    redis:      time-to-live: 1800000 #设置缓存数据的过期时间

在启动类上加入@EnableCaching注解,开启缓存注解功能y1-14ReggieApplication

package com.itheima.reggie;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;import org.springframework.cache.annotation.EnableCaching;import org.springframework.transaction.annotation.EnableTransactionManagement;//启动类  5@Slf4j  //这个注解是lombok提供的 日志文件@SpringBootApplication@ServletComponentScan //目的是让我们定义的过滤器生效@EnableTransactionManagement  //使我们的事务注解起作用  4-10@EnableCaching //开启spring Cachepublic class ReggieApplication {    public static void main(String[] args) {        SpringApplication.run(ReggieApplication.class,args);        log.info("项目启动成功。。。。!!!***~####");    }}

在SetmealController的list方法上加入@Cacheable注解y1-14SetmealController

/**     * 根据条件查询套餐数据优化  y1-14     * @param setmeal     * @return     */    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId+'_'+#setmeal.status")    @GetMapping("/list")    public R<List<Setmeal>> list(Setmeal setmeal){        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());        queryWrapper.orderByDesc(Setmeal::getUpdateTime);        List<Setmeal> list = setmealService.list(queryWrapper);        return R.success(list);    }

点击套餐,测试报错,是因为我们的返回值是R>而R是我们自己定义的,没有序列化,需要将其继承序列化接口

缓存优化_redis_56

缓存优化_验证码_57

改造R

缓存优化_redis_58

再次重启测试

正常展示

缓存优化_缓存_59

查看缓存

缓存优化_缓存_60

在SetmealController的save和delete方法.上加入CacheEvict注解y1-14SetmealController

//新增套餐  优化  y1-14    @CacheEvict(value = "setmealCache",allEntries = true)    @PostMapping    public R<String> save(@RequestBody SetmealDto setmealDto){        log.info("套餐信息 {}",setmealDto);        setmealService.saveWithDish(setmealDto);        return R.success("新增套餐成功");    }

 /**     * 删除套餐  优化  y1-14     * @param ids     * @return     */    //allEntries = true 表示删除setmealCache底下的所有缓存数据    @CacheEvict(value = "setmealCache",allEntries = true)    @DeleteMapping    public R<String> delete(@RequestParam List<Long> ids){        log.info("ids:{}",ids);        setmealService.removeWithDish(ids);        return R.success("套餐数据删除成功");    }

测试再新增之前套餐缓存还在,新增之后就没了

缓存优化_缓存_61

缓存优化_spring cache_62

新增的套餐

缓存优化_redis_63

6.3提交代码和合并y1-15提交

缓存优化_spring cache_64

缓存优化_redis_65

合并y1-15

切换回master,然后合并

缓存优化_验证码_66

随便找一个修改过的代码,合并成功

缓存优化_验证码_67