在之前的文章中,我们写了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);