1. 简介
缓存是常用的优化手段之一,可以将复杂的计算结果或查询结果保存在快速的缓存中,下次请求同样的数据时可以直接从缓存中获取结果而不用再去查询数据库或做复杂的计算。Spring Boot中提供了缓存框架来方便实现数据缓存,也支持自定义缓存注解来实现特定需求的缓存操作。本文将介绍如何通过自定义缓存注解将数据库数据缓存到Redis中。
2. 环境
在介绍具体实现之前,先来介绍一下本文相关的环境:
Spring Boot版本:2.x
Redis版本:4.x
3. 配置Redis
首先需要在项目中引入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=
其中host为Redis的主机名,port为端口号,password为访问Redis的密码。如果Redis服务未设置密码则password可不填或直接填写空字符串。
4. 创建自定义注解
在实现数据缓存前,需要先定义一个自定义注解,可以通过它来标记需要进行缓存的方法或类。下面是一个示例:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomCache {
String key();
long expire() default 60;
}
这里使用了Java的注解机制来定义了一个名为CustomCache的注解,用@Target来指定注解的作用范围,这里包括了方法和类;用@Retention来指定注解的生命周期,这里设置为运行时期;用两个成员变量key和expire来存储缓存的键和过期时间,其中过期时间的单位为秒。
5. 配置自定义注解
接着在Spring Boot配置类中添加@EnableCaching注解,并实现CacheManager接口的bean。这里使用Redis作为缓存提供器,因此需要引入org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer类来帮助配置RedisCacheManager。具体实现如下:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Value("${spring.cache.redis.time-to-live}")
private Duration timeToLive;
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory,
RedisCacheConfiguration cacheConfiguration,
RedisCacheManagerBuilderCustomizer customizer) {
RedisCacheWriter cacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
customizer.customize(new RedisCacheManagerBuilderCustomizer.RedisCacheManagerBuilder() {
@Override
public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {
builder.cacheWriter(cacheWriter).cacheDefaults(cacheConfiguration);
}
});
return new RedisCacheManager(cacheWriter, cacheConfiguration);
}
@Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.entryTtl(timeToLive);
}
}
这里使用了@EnableCaching来开启缓存注解支持,同时添加了一个CacheConfig配置类,实现了CachingConfigurerSupport接口。配置类定义了一个cacheManager()方法用于创建RedisCacheManager bean,同时引入了RedisCacheManagerBuilderCustomizer用于改变默认设置,同时通过cacheConfiguration()方法设置了RedisCacheConfiguration,为缓存提供了序列化方式和过期时间。
6. 实现缓存逻辑
最后是演示如何实现缓存逻辑。这里使用一个UserService来作为示例,其中包含了一个根据用户ID查询用户信息的方法,该方法的返回值为User对象。
public interface UserService {
User getUserById(Long id);
}
@Service
@CustomCache(key = "'USER-' + #id", expire = 600)
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User getUserById(Long id) {
return userDao.findById(id).orElse(null);
}
}
在这里使用了之前定义的CustomCache注解,并通过key属性设置了缓存的键,过期时间则为expire属性。当调用getUserById()方法时,若缓存中存在以该键值为键的缓存,则直接从缓存中返回结果;若缓存中不存在,则查询数据库并将结果保存到缓存中。
7. 测试
最后,可以通过创建单元测试来验证实现是否正常。下面是一个简单的测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testGetUserById() {
User user = userService.getUserById(1L);
System.out.println(user);
User user2 = userService.getUserById(1L);
System.out.println(user2);
Assert.assertEquals(user, user2);
}
}
这里使用了JUnit和SpringBootTest来创建测试,并通过Autowired注解注入了UserService。在测试代码中,先调用getUserById()方法获取User对象,然后再次调用该方法获取User对象。由于第二次调用时缓存中已存在相应的缓存条目,因此该方法直接从缓存中返回结果。
8. 总结
本文介绍了如何在Spring Boot中通过自定义缓存注解实现数据库数据缓存到Redis中的方案。首先要引入Redis相关依赖,并在配置文件中配置Redis连接信息。然后定义自定义注解来标记需要进行缓存的方法或类,配置缓存管理器以及相关的属性。最后在实现方法的同时使用自定义注解来实现缓存逻辑。此外,本文也介绍了如何通过简单的单元测试来验证实现是否正常。通过自定义缓存注解的方式,可以更加便捷地实现数据缓存,同时也可以更好地满足特定的需求。