redis缓存神器之@Cacheable注解详解

 更新时间:2025年11月07日 17:16:29   作者:剽悍一小兔  
文章介绍了如何在SpringBoot中使用Redis和@Cacheable注解进行缓存分页数据,以及在数据更新时如何更新缓存,通过使用@EnableCaching、@Cacheable、@CachePut和@CacheEvict注解,可以简化缓存操作并提高系统性能

redis之@Cacheable注解

在之前的文章中,我们写了redis结合springboot做缓存分页的方法:

在Spring Boot中结合Redis进行缓存分页数据

可以通过以下步骤实现:

在 pom.xml 文件中添加 Redis 相关依赖:

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

在 application.properties 文件中配置 Redis 连接信息:

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=

创建一个 RedisTemplate 对象,用于操作 Redis 缓存:

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }
}

在 Service 层中,使用 RedisTemplate 对象进行缓存操作。

例如,对于分页查询操作,可以将查询结果缓存到 Redis 中,下次查询时先从 Redis 中获取数据,如果缓存中不存在,则进行数据库查询,并将查询结果缓存到 Redis 中:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserDao userDao;

    @Override
    public List<User> getUsersByPage(int pageNum, int pageSize) {
        String key = "user:page:" + pageNum + ":" + pageSize;
        List<User> users = (List<User>) redisTemplate.opsForValue().get(key);
        if (users == null) {
            PageHelper.startPage(pageNum, pageSize);
            users = userDao.getUsers();
            PageInfo<User> pageInfo = new PageInfo<>(users);
            redisTemplate.opsForValue().set(key, pageInfo, 1, TimeUnit.MINUTES);
        }
        return users;
    }
}

在上述代码中,使用了 PageHelper 插件进行分页查询,并将查询结果缓存到 Redis 中,缓存时间为 1 分钟。下次查询时,如果缓存中存在数据,则直接从缓存中获取,避免了频繁查询数据库的操作。

以上就是 Spring Boot 结合 Redis 进行缓存分页数据的实现方法。需要注意的是,缓存的数据需要根据实际情况进行设置过期时间,避免缓存数据过期后仍然被使用。

但是,以上代码还是存在问题的,如果page数据发生了变化怎么办,redis获取的还是老数据啊!

所以,我们需要在数据更新的时候,也要更新缓存里面的数据。

来唠唠怎么更新缓存和简化这些操作

Spring Boot提供了一个注解@EnableCaching来启用缓存功能。在启用缓存功能后,可以使用注解来对某个方法进行缓存。

首先,在pom.xml文件中添加redis依赖:

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

在application.properties文件中配置redis连接信息:

spring.redis.host=127.0.0.1
spring.redis.port=6379

在启动类上添加@EnableCaching注解,开启缓存功能:

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

在需要进行缓存的方法上添加@Cacheable注解:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Cacheable(value = "userCache", key = "#id") // 添加缓存注解
    public User getUserById(Long id) {
        return userDao.getUserById(id);
    }
}

其中,@Cacheable注解有两个重要的参数:value和key。value表示缓存的名称,如果没有指定则使用默认缓存;key表示缓存的key值,可以使用SpEL表达式来表示。

这样,当第一次调用getUserById方法时,会将返回结果缓存起来,下次再调用该方法时,直接从缓存中获取结果,而不是执行方法体。如果需要更新缓存,可以调用@CachePut注解或@CacheEvict注解来实现。

需要注意的是,在使用@Cacheable注解时,被缓存的方法不能抛出异常,否则会导致缓存失效。

当使用@Cacheable注解后,如果需要更新缓存,可以通过调用@CachePut注解来更新缓存。

@CachePut注解的使用方法和@Cacheable注解类似。在需要更新缓存的方法上添加@CachePut注解,并指定value和key值。

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Cacheable(value = "userCache", key = "#id")
    public User getUserById(Long id) {
        return userDao.getUserById(id);
    }

    @Override
    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        userDao.updateUser(user);
        return user;
    }
}

在更新数据时,先调用更新方法updateUser,然后再调用查询方法getUserById,此时会更新缓存中的数据。

// 更新用户信息
User user = new User();
user.setId(1L);
user.setName("new name");
userService.updateUser(user);

// 查询用户信息,会从缓存中获取
User userFromCache = userService.getUserById(1L);

如果需要删除缓存中的数据,可以通过调用@CacheEvict注解来实现。

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Cacheable(value = "userCache", key = "#id")
    public User getUserById(Long id) {
        return userDao.getUserById(id);
    }

    @Override
    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        userDao.updateUser(user);
        return user;
    }

    @Override
    @CacheEvict(value = "userCache", key = "#id")
    public void deleteUserById(Long id) {
        userDao.deleteUserById(id);
    }
}

在删除数据时,先调用删除方法deleteUserById,然后再调用查询方法getUserById,此时会重新从数据库中获取数据。

// 删除用户信息
userService.deleteUserById(1L);

// 查询用户信息,会重新从数据库中获取
User userFromDB = userDao.getUserById(1L);

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Redis不使用 keys 命令获取键值信息的方法

    Redis不使用 keys 命令获取键值信息的方法

    这篇文章主要介绍了Redis 不使用 keys 命令获取键值信息的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-08-08
  • redis-sentinel基础概念及部署流程

    redis-sentinel基础概念及部署流程

    Redis Sentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包括Sentinel节点、主节点和从节点,部署需配置参数,验证主节点变化即成功
    2025-08-08
  • Redis Sentinel服务配置流程(详解)

    Redis Sentinel服务配置流程(详解)

    下面小编就为大家带来一篇Redis Sentinel服务配置流程(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Redis热点Key问题的完整解决方案:

    Redis热点Key问题的完整解决方案:

    热点Key就像双十一爆款商品,1%的Key承担了90%的流量!本文将用电商案例,教你如何智能分流、化解压力,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2025-08-08
  • Redis内存碎片原理深入分析

    Redis内存碎片原理深入分析

    这篇文章主要为大家介绍了Redis内存碎片原理深入分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Redis实现排名功能的示例代码

    Redis实现排名功能的示例代码

    本文主要介绍了Redis实现排名功能的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 完美解决linux上启动redis后配置文件未生效的问题

    完美解决linux上启动redis后配置文件未生效的问题

    今天小编就为大家分享一篇完美解决linux上启动redis后配置文件未生效的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • Redis实现分布式事务的示例

    Redis实现分布式事务的示例

    Redis虽不支持传统SQL数据库ACID特性的事务,但提供了事务特性,允许多命令捆绑执行,通过命令MULTI、EXEC、DISCARD、WATCH实现,感兴趣的可以了解一下
    2024-10-10
  • 使用redis获取自增序列号实现方式

    使用redis获取自增序列号实现方式

    这篇文章主要介绍了使用redis获取自增序列号实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • redis 存储对象的方法对比分析

    redis 存储对象的方法对比分析

    这篇文章主要介绍了redis 存储对象的方法对比分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论