在之前的文章中,我们写了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 {@Beanpublic 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 {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate UserDao userDao;@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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);