【未完成】Redis(四)Spring Boot 整合 spring-boot-starter-data-redis

一、spring-boot-starter-data-redis提供的功能

1、连接池自动管理,提供了一个高度封装的“RedisTemplate”类

2、针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口

  • ValueOperations:简单K-V操作
  • HashOperations:针对map类型的数据操作
  • ListOperations:针对list类型的数据操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作

3、提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations:

  • BoundValueOperations
  • BoundHashOperations
  • BoundListOperations
  • BoundSetOperations
  • BoundZSetOperations

4、将事务操作封装,有容器控制。

5、针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)

  • JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。
  • StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
  • JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】
  • OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

 

二、依赖和Redis配置

1、maven依赖 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

2、application.yml配置

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接超时时间(毫秒)
    timeout: 3000
    # 连接池配置
    pool:
      # 连接池最大连接数(使用负值表示没有限制)
      max-active: 8
      # 连接池中的最大空闲连接
      max-idle: 8
      # 连接池中的最小空闲连接
      min-idle: 0
      # 连接池最大阻塞等待时间(使用负值表示没有限制)
      max-wait: -1

 

三、RedisTemplate配置及其相关方法

1、RedisTemplate介绍

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。

注意 RedisTemplate是一个key和value都是泛型的模板类,一般情况下key为String类型,如:RedisTemplate<String,Object>。此外,如果没特殊情况,切勿定义成RedisTemplate<Object, Object>,否则根据里氏替换原则,使用的时候会造成类型错误 

StringRedisTemplate RedisTemplate

  • 两者的关系是StringRedisTemplate继承RedisTemplate。

  • 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。

  • SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

    StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

    RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

 

2、RedisTemplate数据操作对象(重要)

RedisTemplate 操作数据的对象有 opsForXXX 和 boundXXXOps 两种(XXX为value的类型)

  • opsForXXX:获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value
  • boundXXXOps:后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value

2.1、opsForXXX

针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口 

其实这里的ops相当于options, 是RedisTemplate对各种不同的Redis数据类型进行操作

获取对象方法(无参数)返回的操作对象描述
RedisTemplate.opsForValue()ValueOperations<String, Object>操作字符串
RedisTemplate.opsForHash()HashOperations<String, String, Object>操作Hash
RedisTemplate.opsForList()ListOperations<String, Object>操作List
RedisTemplate.opsForSet()SetOperations<String, Object>操作Set
RedisTemplate.opsForZSet()ZSetOperations<String, Object>操作有序Set 

关于计数的API(increment)有一个bug,需要各位使用中注意,通过increment计数以后,通过get方式获取计数值的时候可能会抛出EOF异常(和本地的jdk以及redis的编译版本有关),可以考虑使用boundValueOps(key).get(0,-1)获取计数值。 

2.2、boundXXXOps

提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations:

获取对象方法(有参数)返回的操作对象描述
RedisTemplate.boundValueOps(K key)BoundValueOperations<String, Object>操作字符串
RedisTemplate.boundHashOps(K key)BoundHashOperations<String, String, Object>操作Hash
RedisTemplate.boundListOps(K key)BoundListOperations<String, Object>操作List
RedisTemplate.boundSetOps(K key)BoundSetOperations<String, Object>操作Set
RedisTemplate.boundZSetOps(K key)BoundZSetOperations<String, Object>操作有序Set 


3、Redis配置类RedisConfig(重要)

主要用来配置 key value 序列化加载配置文件中的相关参数

新建一个redisConfig类,进行相关bean的配置(代码向下看)

 3.1 序列化

spring-redis中使用了RedisTemplate来进行redis的操作,通过泛型的K和V设置键值对的对象类型。这里使用了string作为key的对象类型,值为Object。

对于Object,spring-redis默认使用了jdk自带的序列化,不推荐使用默认(可读性太差)。建议使用 Json  的序列化方式

当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。

Spring Data JPA 为我们提供了下面的 Serializer:

GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer

序列化方式对比:

  • JdkSerializationRedisSerializer: 使用JDK 提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
  • Jackson2JsonRedisSerializer 使用Jackson 库将对象序列化为 JSON 字符串。优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息

 可能会遇到的问题:

  1. RedisTemplate的 key 指定成 StringRedisSerializer 序列化会报类型转换错误,如XXX类不能转换成String。
  2. 使用 Jackson2JsonRedisSerializer 序列化的时候,如果实体类上没有set方法反序列化会报错

 

代码示例: 

package com.marvin.demo.config;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * reids 相关bean的配置
 */
@Configuration
public class RedisConfig {
	/**
	 * redisTemplate相关配置
	 * @param factory
	 * @return
	 */
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		// 配置连接工厂
		template.setConnectionFactory(factory);

		/** 下面是设置序列化KEY VALUE的方式
		 * (默认使用JDK的序列化方式)
		 */
		/** 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(序列化方式选其一)*/
		Jackson2JsonRedisSerializer jacksonSeial = getJeckson2Serializer();
		//使用StringRedisSerializer来序列化和反序列化redis的key值和value值
		template.setKeySerializer(new StringRedisSerializer());
		template.setValueSerializer(jacksonSeial);
		// 设置hash key 和value序列化模式
		template.setHashKeySerializer(new StringRedisSerializer());
		template.setHashValueSerializer(jacksonSeial);

		/** 这里使用的是fastjson来做value的序列化(序列化方式选其一)*/
//		template.setKeySerializer(new StringRedisSerializer());
//		template.setValueSerializer(new FastJsonRedisSerializer(Object.class));
//		template.setHashKeySerializer(new StringRedisSerializer());
//		template.setHashValueSerializer(new StringRedisSerializer());

		/** 必须执行这个函数,初始化RedisTemplate (初始化操作)加载配置后执行*/
		template.afterPropertiesSet();
		return template;
	}
	/** 
	 * Jackson2JsonRedisSerializer序列化配置
	 */
	private Jackson2JsonRedisSerializer getJeckson2Serializer(){
		Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
		ObjectMapper om = new ObjectMapper();
		// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jacksonSeial.setObjectMapper(om);
		return jacksonSeial;
	}

	/**
	 * 对redis字符串类型数据操作
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
		return redisTemplate.opsForValue();
	}
	/**
	 * 对hash类型的数据操作
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
		return redisTemplate.opsForHash();
	}
	/**
	 * 对链表类型的数据操作
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
		return redisTemplate.opsForList();
	}
	/**
	 * 对无序集合类型的数据操作
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
		return redisTemplate.opsForSet();
	}
	/**
	 * 对有序集合类型的数据操作
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
		return redisTemplate.opsForZSet();
	}
}

注意:

1、RedisTemplate 必须执行 afterPropertiesSet() 函数,这是初始化操作,加载配置后执行

 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值