介绍
个人springdome 测试
软件架构
redis 基于 Lettuce 学习(springboot2.x其中使用的是Lettuce,springboot1.x系列中,其中使用的是jedis)
a. Lettuce 和 Jedis 的定位都是Redis的client,所以他们当然可以直接连接redis server。
b. Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
c. Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
1、pom包,yml配置
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: adminroot
username: root
url: jdbc:mysql://localhost:3306/vue_authentication?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
redis:
port: 6379
host: 127.0.0.1
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
2、config 配置
@EnableCaching
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
/**
* 配置自定义redisTemplate
*
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setValueSerializer(jackson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* json序列化
*
* @return
*/
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
return serializer;
}
/**
* 配置缓存管理器
*
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置
config = config.entryTtl(Duration.ofMinutes(1))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("timeGroup");
cacheNames.add("user");
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>(10);
configMap.put("timeGroup", config);
configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));
// 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
// 一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}
3、简单使用
@Test
public void contextLoads() {
// redis存储数据
String key = "name";
redisTemplate.opsForValue().set(key, "yukong");
// 获取数据
String value = (String) redisTemplate.opsForValue().get(key);
System.out.println("获取缓存中key为" + key + "的值为:" + value);
User user = new User();
user.setUsername("yukong");
user.setSex(18);
user.setId(1L);
String userKey = "yukong";
redisTemplate.opsForValue().set(userKey, user);
User newUser = (User) redisTemplate.opsForValue().get(userKey);
System.out.println("获取缓存中key为" + userKey + "的值为:" + newUser);
}
4、使用缓存(概念介绍)
Spring Cache常见概念介绍
名称 | 解释 |
---|---|
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存。与@Cacheable区别在于是否每次都调用方法,常用于更新 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
@CacheConfig | 统一配置本类的缓存注解的属性 |
注解(@Cacheable/@CachePut/@CacheEvict)的主要参数
名称 | 解释 |
---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 e.g. @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 e.g. @Cacheable(value=”testcache”,key=”#id”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存/清除缓存 e.g.@Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
unless | 否定缓存。当条件结果为TRUE时,就不会缓存。 e.g.@Cacheable(value=”testcache”,unless=”#userName.length()>2”) |
allEntries(@CacheEvict ) | 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 e.g. @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation(@CacheEvict) | 是否在方法执行前就清空,缺省为 false,如果指定为 true, 则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 e.g. @CachEvict(value=”testcache”,beforeInvocation=true) |
5、service层代码
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User saveUser(User user) {
userMapper.save(user);
// 返回用户信息,带id
return user;
}
/**
* @param id 主键id
* @return
* @CacheEvict 应用到删除数据的方法上,调用方法时会从缓存中删除对应key的数据
* condition 与unless相反,只有表达式为真才会执行。
*/
@CacheEvict(value = "user", key = "#root.args[0]", condition = "#result eq true")
@Override
public Boolean removeUser(int id) {
// 如果删除记录不为1 则是失败
return userMapper.deleteById(id) == 1;
}
/**
* @param id 主键id
* @return
* @Cacheable 应用到读取数据的方法上,先从缓存中读取,如果没有再从DB获取数据,然后把数据添加到缓存中
* key 缓存在redis中的key
* unless 表示条件表达式成立的话不放入缓存
*/
@Cacheable(value = "user", key = "#root.args[0]", unless = "#result eq null ")
@Override
public User getById(int id) {
return userMapper.selectById(id);
}
/**
* @param user 用户信息
* @return
* @CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存
*/
@CachePut(value = "user", key = "#root.args[0]", unless = "#user eq null ")
@Override
public User updateUser(User user) {
userMapper.update(user);
return user;
}
}
6、接口测试
@Autowired
private UserService userService;
@PostMapping
public User save(@RequestBody User user) {
return userService.saveUser(user);
}
@PutMapping
public User update(@RequestBody User user) {
return userService.updateUser(user);
}
@DeleteMapping(value = "/id/{id}")
public Boolean delete(@PathVariable int id) {
return userService.removeUser(id);
}
@GetMapping(value = "/id/{id}")
public User findById(@PathVariable int id) {
return userService.getById(id);
}
注意版本
reference
1、SpringBoot进阶教程(五十三)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用
2、【SpringBoot2.0系列07】SpringBoot之redis使用(Lettuce版本)
3、不错的小知识点RedisTemplate用法详解