SpringBoot - 整合Redis缓存cache及键值序列化

前面的SpringCache缓存说过在没有引入其他缓存中间件时,默认使用的是ConcurrentMapCacheManager=ConcurrentMapCache,是将数据保存在ConcurrentMap<Object, Object>中。
在实际开发中,我们一般都会使用redismemcachedehcache来作为缓存中间件。

整合Redis

Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
当我们引入Reidsstarter依赖的时候,使用RedisCacheManagerRedisCacheManager会帮我们创建RedisCache来作为缓存组件,RedisCache通过操作redis缓存数据。

1、引入Redis的starter的依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池 - luttuce依赖该连接池 -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.4.2</version>
</dependency>

2、配置yml配置文件

spring:
  redis:
    host: 127.0.0.1  # Redis连接地址
    port: 6379 # redis连接端口
    lettuce: # 使用lettuce客户端
      pool:
        max-active: 8 # 连接池最大连接数(负值表示没有限制)
        max-idle: 8 # 连接池的最大空闲连接
        min-idle: 0 # 连接池的最小空闲连接
        max-wait: -1ms # 连接池最大阻塞等待时间(赋值表示没有限制)
    database: 0     # 默认使用索引为0的数据库
    timeout: 5000ms # 连接超时时间

3、序列化配置
Reids默认使用的是JDK的序列化机制,我们通过RedisDesktopManager去查看存储的数据,是无法用肉眼看出存的是什么的。
JDK序列化机制
比如说我们要存一个对象进去,并且想直接肉眼看到是一个怎么样的数据,可以通过修改配置,让其以Json的格式去保存。
创建一个配置类继承CachingConfigurerSupport

@Configuration
public class RedisConfiguration extends CachingConfigurerSupport {
   
    /**
     * 采用RedisCacheManager作为缓存管理器
     * @param connectionFactory Redis连接工厂 - 配置的Luttuce,这里实际传递的就是LuttuceFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory){
        RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);
        return redisCacheManager;
    }

    /**
     * 解决键值序列化问题
     * @param connectionFactory Redis连接工厂
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

4、测试一下

// 注入RedisTemplate
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
// 向Redis中存数据
@GetMapping("/test")
public String test(){
    BoundHashOperations boundHashOps = redisTemplate.boundHashOps("User");
    List list = new ArrayList();
    User user1 = new User("柳成荫", "男", 22);
    list.add(user1);
    list.add(user1);
    boundHashOps.put("3",list);
    return "ok";
}
// 向Redis取数据
@GetMapping("/test1")
public List test1(){
    BoundHashOperations boundHashOps = redisTemplate.boundHashOps("User");
    List<User> users = (List<User>) boundHashOps.get("3");
    return users;
}

可以看到确实存入的是JSON序列化的结果
RedisDesktopManager
取出来也是没有问题的
在这里插入图片描述

使用Cache

上面的RedisConfiguration中已经指定了缓存管理器为RedisCacheManager,也就是说Cache现在是可以存到Redis中的。

1、创建POJO类
@Data
public class User implements Serializable {
    private Long id;
    private String name;
    private String sex;
    private Integer age;

    public User(){}

    public User(Long id,String name, String sex, Integer age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}
2、创建Service类

为了方便测试,直接创建了一个Service类,并且直接通过SpringBooTest来直接调用测试。

@Service
@CacheConfig(cacheNames = "user_cache")   // 缓存名
public class UserService {
    @Cacheable(key = "#id")  // 缓存key
    public User getUser(Long id){
        System.out.println("直接获取User信息:");
        User user = new User(1L,"柳成荫","男",22);
        return user;
    }
}
3、测试
@Autowired
private UserService userService;
@Test
public void test1(){
	User user = userService.getUser(2L);
	System.out.println(user);
}
4、测试结果

通过RedisDesktopManager查看存储情况。
在这里插入图片描述

5、可以使用自定义的Key

使用自定义Key规则,直接在RedisConfiguration中重写KeyGenerator方法即可,示例:

/**
 * 自定义生成Key的规则
 * @return
 */
@Override
public KeyGenerator keyGenerator() {
	return new KeyGeneratorImpl();
}
/**
 * 生成Key的规则
 */
private class KeyGeneratorImpl implements KeyGenerator{
	@Override
	public Object generate(Object target, Method method, Object... params) {
		StringBuilder sb = new StringBuilder();
		sb.append(target.getClass().getName()).append("."); // 追加类名
		sb.append(method.getName()).append("(");
		for (Object object : params){
			sb.append(object.toString()).append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(")");
		System.out.println("调用了Redis缓存Key:" + sb.toString());
		return sb.toString();
	}
}

在Service类上或类中方法上指定缓存名即可:

@Service
public class UserService {
    @Cacheable(value = "abc")  // 缓存名:abc
    public User getUser(Long id){
        System.out.println("直接获取User信息:");
        User user = new User(1L,"柳成荫","男",22);
        return user;
    }
}

测试之后,结果如下:
在这里插入图片描述

序列化总结

JdkSerializationRedisSerializer是默认序列化方式,是最简单的也是最安全的,只要实现了Serializer接口,实体类型,集合,Map等都能序列化与反序列化,但缺陷是序列化数据很多,会对redis造成更大压力,且可读性和跨平台基本无法实现
Jackson2JsonRedisSerializer用的是json的序列化方式,能解决JdkSerializationRedisSerializer带来的缺陷。
jdk的序列化方式字符串会比json序列化文本大5倍。

SpringCache+Redis可以参考:SpringBoot整合RedisSpringDataRedis最佳实践

发布了100 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40885085/article/details/104960167
今日推荐