基于SpringCache实现数据缓存

SpringCache

SpringCache是一个框架实现了基本注解的缓存功能,只需要简单的添加一个@EnableCaching 注解就能实现缓存功能

  • SpringCache框架只是提供了一层抽象,底层可以切换CacheManager接口的不同实现类即使用不同的缓存技术,默认的实现是ConcurrentMapCacheManager
  • ConcurrentMapCacheManager是基于内存存储数据的,所以重启服务后缓存数据就会消失
CacheManger描述
EhCacheCacheManager使用EhCache作为缓存技术
GuavaCacheManager使用Googke的GuavaCache作为缓存技术
RedisCacheManager使用Rdis作为缓存技术

环境准备

第一步: 定义实体类User且实现序列化接口

@Data
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    private String name;
    private int age;
    private String address;
}

第二步: 定义Mapper接口

@Mapper
public interface UserMapper extends BaseMapper<User>{
}

第三步: 定义UserService接口及其实现类

public interface UserService extends IService<User> {
    
}

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    
}

第四步: 定义接口

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    // 默认的实现是ConcurrentMapCacheManager
    @Autowired
    private CacheManager cacheManager;
    
    @Autowired
    private UserService userService;
}

第五步: 开启缓存注解功能

@Slf4j
@SpringBootApplication
// 开启缓存注解功能
@EnableCaching
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class,args);
        log.info("项目启动成功...");
    }
}

SpringCache常用注解

因为缓存的数据key一定是唯一的,所以key支持SpEL表达式来动态的计算key(条件判断也支持SpEL表达式)

  • #result: 代表方法的返回值,如#result.id表示获取返回值对象的id属性值作为key
  • #root: 代表整个方法对象,如#root.args[0].id表示获取方法的第一个参数的id属性值作为key
  • #p[i]: 代表方法的参数,如p[0].id表示获取方法的第一个参数的id属性值作为key
  • #方法参数名: 代表方法的参数,如#user.id获取参数user对象的id属性值作为key

condition和unless的区别

  • condition: 表示满足条件才进行缓存,不支持SpEL表达式中的#result
  • unless: 表示满足条件不进行缓存,支持SpEL表达式中的#result
注解说明
@EnableCaching开启缓存注解功能
@Cacheable在方法执行前spring先查看缓存中是否有数据,如果有数据则直接返回缓存数据;若没有数据调用方法并将方法返回值放到缓存中(查询方法)
@CachePut将方法的返回值放到缓存中(适合新增的方法)
@CacheEvict将一条或者多条数据从缓存中删除(适合删除和更新的方法啊)

@CachePut(新增)

@CachePut主要针对方法配置,能够根据方法的请求参数将方法的返回值进行缓存,每次都会触发真实方法的调用

注解说明举例
value指定缓存的名称必须指定至少一个@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的,表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

测试新增的方法将方法的返回值进行缓存

在这里插入图片描述

@CachePut(value="userCache",key="#user.id")
@PostMapping
public User save(User user){
    userService.save(user);
    return user;
}

查看ConcurrentMapCacheManager中缓存的结果

在这里插入图片描述

@CachEvict(删除)

@CachEvict主要针对方法配置,能够根据一定的条件将缓存中的数据进行清空

注解说明举例
value缓存的名称必须指定且至少一个@Cacheable(value=”mycache”)或者@Cacheable(value={“cache1”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空某类缓存下的所有数据,默认为false@CachEvict(value=”testcache”,allEntries=true)
beforelnvocation是否在方法执行前就清空,缺省为false,如果指定为true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存@CachEvict(value=”testcache”, beforelnvocation=true)

测试删除的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#user.id")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
    userService.removeById(id);
}

测试更新的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#id")
@PutMapping
public User update(User user){
    userService.updateById(user);
    return user;
}

@Cacheable(查询)

@Cacheable注解主要针对方法配置,如果缓存中没有数据能够根据方法的请求参数对方法结果进行缓存,如果缓存中有数据则不会调用方法

  • 如果查询的数据在数据库中也查询不到则会缓存一个null,这样下次再查询这个数据时直接返回null,避免缓存穿透
注解说明举例
value指定缓存的名称表示一类缓存,每个缓存名称下可以存储多个key@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key(唯一)指定缓存数据的key(可以为空),表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless指定缓存的条件(可以为空)返回true或者false,满足条件不进行缓存@Cacheable(value=”testcache”,unless=”#userName.length()>2”)

测试根据id查询的方法,如果缓存中没有数据则将方法返回值进行缓存,如果缓存中有对应数据则不调用方法直接返回缓存的数据

在这里插入图片描述

@Cacheable(value="userCache",key="#id")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}
// 查询结果为null不缓存,condition不支持#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")//查询条件和id和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;
}

查询缓存的结果

在这里插入图片描述

使用SpringCache基于redis

使用步骤

第一步: 在SpringBoot项目中使用缓存技术只需要在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存技术支持即可

  • 如果想使用SpringCache的基本功能只需要导入spring-context依赖即可(导入spring-boot-starter-web会自动传递)
<!--使用Redis作为缓存技术,里面包含CacheManager接口的实现类-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--对SpringCache中CacheManager接口的实现类进行了扩展-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

第二步: 在application.yml文件中配置redis相关的配置

spring:
  redis:
    host: 101.XXX.XXX.160 #redis服务所在地址
    password: root
    port: 6379
    database: 0
  cache:
    redis:
      time-to-live: 3600000 #设置缓存有效期为一小时(单位毫秒),如果不设置则一直存活
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    // 底层实现是RedisCacheManager
    @Autowired
    private CacheManager cacheManager;
    
    @Autowired
    private UserService userService;
}

第三步: 在启动类上加@EnableCaching注解表示开启缓存注解功能

@Slf4j
@SpringBootApplication
// 开启缓存注解功能
@EnableCaching
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class,args);
        log.info("项目启动成功...");
    }
}

第四步: 在Controller的方法上加上@Cacheable,@CachePut,@CacheEvict缓存注解进行缓存操作

在这里插入图片描述

// 查询结果为null不缓存,condition不支持#result
@Cacheable(value="userCache",key="#id",unless="#result==null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}
  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值