> 文章列表 > 缓存优化----SpringCache

缓存优化----SpringCache

缓存优化----SpringCache

spring cache

  • spring Cache介绍

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

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

    cacheManager是spring提供的各种缓存技术抽象接口

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

    CacheManager 描述
    EhCacheCacheManager 使用EhCache作为缓存技术
    GuavaCacheManager 使用Google的GuavaCache作为缓存技术
    RedisCacheManager 使用Redis作为缓存技术
  • spring cache常用注解

    注解 说明
    @EnableCaching 开启缓存注解功能
    @Cacheable 在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
    @CachePut 将方法的返回值放到缓存中
    @CacheEvict 将一条或多条数据从缓存中删除

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

    例如:使用redis作为缓存技术,只需要导入spring data redis的maven坐标即可

  • spring cache使用方式

    在springboot项目中使用springcache的操作步骤(使用redis缓存技术):

    1. 导入maven坐标

      <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>
      
    2. 配置application.yml

      redis:host: 172.17.2.94port: 6379password: root@123456database: 0
      cache:redis:time-to-live: 1800000 #设置缓存过期时间,可选
      
  1. 在启动类上加上@EnableCaching注解,开启缓存注解功能
  2. 在Controller的方法上加入@Cacheable、@CacheEvict等注解,进行缓存操作

userController

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@Autowiredprivate CacheManager cacheManager;@Autowiredprivate UserService userService;/*** CachePut:将方法返回值放入缓存* value:缓存的名称,每个缓存名称下面可以有多个key* key:缓存的key*/@CachePut(value = "userCache",key = "#user.id")@PostMappingpublic User save(User user){userService.save(user);return user;}/*** CacheEvict:清理指定缓存* value:缓存的名称,每个缓存名称下面可以有多个key* key:缓存的key*/@CacheEvict(value = "userCache",key = "#p0")//p0代表第一个参数,id是第一个参数等价//@CacheEvict(value = "userCache",key = "#root.args[0]")//@CacheEvict(value = "userCache",key = "#id")@DeleteMapping("/{id}")public void delete(@PathVariable Long id){userService.removeById(id);}//@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")@PutMappingpublic User update(User user){userService.updateById(user);return user;}/*** Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中* value:缓存的名称,每个缓存名称下面可以有多个key* key:缓存的key* condition:条件,满足条件时才缓存数据* unless:满足条件则不缓存*/
//    @Cacheable(value = "userCache",key = "#id",condition = "#result != null")//在源码中不能使用result这个参数,而unless可以使用result@Cacheable(value = "userCache",key = "#id",unless = "#result == null")@GetMapping("/{id}")public User getById(@PathVariable Long id){User user = userService.getById(id);return user;}@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;}
}

pom.cml

<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>

缓存套餐数据

  • 实现思路

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

具体的实现思路如下:

  1. 导入springcache和redis相关maven坐标

缓存优化----SpringCache

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

缓存优化----SpringCache

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

缓存优化----SpringCache

  1. 在SetmealController的list方法上加入@Cacheable注解

注意:返回值无法序列化 报错: DefaultSerializer requires a Serializable payload but received an object of type [com.itheima.reggie.common.R]

解决:

public class R<T> implements Serializable {//将R进行序列化不然进行SpringCache的时候会报错

报错:RedisCommandExecutionException: ERR wrong number of arguments for 'set' command

原因:redis版本原因,版本太低了,更换一个高点的redis版本就可以解决

缓存优化----SpringCache

  1. 在SetmealController的save和delete方法上加入CacheEvict注解
  • 代码改造
/*
* 删除套餐
* */
@DeleteMapping
@CacheEvict(value = "setmealCache",allEntries = true)//allEntries = true 该代码的意思是清除缓存中所有的数据
public R<String> delete(@RequestParam List<Long> ids){log.info("ids:{}",ids);setmealService.removeWithDish(ids);return R.success("套餐数据删除成功!!!!");
}
/** 用户端套餐展示,根据条件查询套餐数据* */@GetMapping("/list")@Cacheable(value = "setmealCache",key = "#setmeal.categoryId+'_'+#setmeal.status")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);}
  • 功能测试

缓存优化----SpringCache

问题(报错解决)

报错:RedisCommandExecutionException: ERR wrong number of arguments for 'set' command

原因:redis版本原因,版本太低了,更换一个高点的redis版本就可以解决