我们以spring-boot-starter-data-redis-2.1.7为例,starter本身没有包含任何代码,只是引入了spring-data-redis的依赖,因此肯定是在spring-boot-autoconfigure中加了自动配置:

我们就看下这几个配置类:

其中RedisAutoConfiguration里面就配置了我们常用的RedisTemplate,RedisRepositoriesAutoConfiguration这里面是实现了spring-data规范的一些配置,RedisReactiveAutoConfiguration是当需要用Reactive方式编程的时候用的,本文忽略。

RedisAutoConfiguration

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
//内置了对lettuce和jedis的支持
//但是默认只添加了lettuce的依赖,因此默认是使用的lettuce
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);
return template;}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);
return template;}
}

这里面内置了对lettuce和jedis的支持,因为默认是引入的lettuce的jar,因此默认会使用lettuce去访问redis,同时这里面创建了一个RedisTemplate和一个StringRedisTemplate,一般我们经常会直接注入StringRedisTemplate来访问redis。

首先看下StringRedisTemplate:

public StringRedisTemplate() {setKeySerializer(RedisSerializer.string());setValueSerializer(RedisSerializer.string());setHashKeySerializer(RedisSerializer.string());setHashValueSerializer(RedisSerializer.string());
}

从名字也可以看出来,它在序列化key、value、hash key和hash value的时候都是转化成String存入redis的,RedisSerializer#string:

static RedisSerializer<String> string() {return StringRedisSerializer.UTF_8;
}
public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8);

看下具体的序列化和反序列化的方法:

@Override
public String deserialize(@Nullable byte[] bytes) {return (bytes == null ? null : new String(bytes, charset));
}
@Override
public byte[] serialize(@Nullable String string) {return (string == null ? null : string.getBytes(charset));
}

一眼就能明白,没什么好说的。但是很显然,它只能处理String类型,如果是对象得需要自己手动转化成String才可以,一般我们会把对象转化成json字符串存储到redis里面。

我们回头再来看下RedisTemplate,RedisTemplate#afterPropertiesSet:

@Overridepublic void afterPropertiesSet() {boolean defaultUsed = false;//判断是否幽默ren的序列化器if (defaultSerializer == null) {//默认是采用jdk自带的序列化,//也就是说必须得实现Serializable接口才行defaultSerializer = new JdkSerializationRedisSerializer(classLoader != null ? classLoader : this.getClass().getClassLoader());}//默认j就是启用的if (enableDefaultSerializer) {//key、value、hash key、hash value都使用默认的那个序列化器 if (keySerializer == null) {keySerializer = defaultSerializer;defaultUsed = true;}if (valueSerializer == null) {valueSerializer = defaultSerializer;defaultUsed = true;}if (hashKeySerializer == null) {hashKeySerializer = defaultSerializer;defaultUsed = true;}if (hashValueSerializer == null) {hashValueSerializer = defaultSerializer;defaultUsed = true;}}。。。}

从名字也可以看出来,RedisTemplate默认是采用JDK自带的序列化方式来做序列化器,看一下:

public JdkSerializationRedisSerializer(@Nullable ClassLoader classLoader) {this(new SerializingConverter(), new DeserializingConverter(classLoader));}public SerializingConverter() {this.serializer = new DefaultSerializer();}
public class DefaultSerializer implements Serializer<Object> {@Overridepublic void serialize(Object object, OutputStream outputStream) throws IOException {if (!(object instanceof Serializable)) {throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +"but received an object of type [" + object.getClass().getName() + "]");}ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(object);objectOutputStream.flush();}
}

很清楚了,最终是使用ObjectOutputStream和ObjectInputStream来读写对象,因此对象必须得实现Serializable接口才可以,最终是以二进制的格式存储到redis里面,比如:

很显然,这种序列化方式的可读性太不友好了。

RedisRepositoriesAutoConfiguration

它实现了spring-data规范,其实就是把redis以数据库dao的形式来访问,这个东西相对就比较复杂了,但是在实际中使用的并不是很多,我们只说一下如何使用。

首先定义一个dao,需要继承CrudRepository:

@Repository
public interface UserDao extends CrudRepository<UserEntity,Long> {}

定义一个数据库实体:

@RedisHash("user")
public class UserEntity {@Idprivate Long id;private String username;private String password;
}

@RedisHash("user")会把user对象存储到一个key是user:id的hash中,比如:

定义service和controller:

@Service
public class UserService {@Autowiredprivate UserDao userDao;public UserEntity save(UserEntity userEntity){userDao.save(userEntity);return userEntity;}public UserEntity findById(Long id){Optional<UserEntity> optional = userDao.findById(id);return optional.isPresent()?optional.get():null;}
}
@RestController
public class UserController {@Autowiredprivate UserService userService;private static AtomicLong id = new AtomicLong(0);@GetMapping("/add_user")public String addUser(String username, String password){long idLong = id.incrementAndGet();userService.save(new UserEntity(idLong, username, password));UserEntity entity = userService.findById(idLong);return entity.toString();}
}

总结一下

- 1.spring-boot-starter-data-redis默认是使用lettuce去访问redis

- 2.内置了StringRedisTemplate和RedisTemplate,应用可以直接使用。当存取对象的时候,StringRedisTemplate需要手动把对象转化成String,RedisTemplate虽然可以直接存取对象,但是需要对象实现Serializable接口,同时在redis库中的可读性比较差。

- 3.由于存在以上的缺点,因此可以把这两个template的优点给融合到一起,既可以直接存取对象,还可以方便人类阅读,当然也可以存取List和基本类型,更重要的是还可以支持给key统一添加前缀,赶快来使用吧:github地址:https://github.com/xjs1919/redis-client。

欢迎扫码查看更多文章:

redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战相关推荐

  1. Spring Boot 核心原理与源码解析 - 目录

    准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...

  2. Redis源码解析——双向链表

    相对于之前介绍的字典和SDS字符串库,Redis的双向链表库则是非常标准的.教科书般简单的库.但是作为Redis源码的一部分,我决定还是要讲一讲的.(转载请指明出于breaksoftware的csdn ...

  3. Redis源码解析——字典基本操作

    有了<Redis源码解析--字典结构>的基础,我们便可以对dict的实现进行展开分析.(转载请指明出于breaksoftware的csdn博客) 创建字典 一般字典创建时,都是没有数据的, ...

  4. Redis源码解析——内存管理

    在<Redis源码解析--源码工程结构>一文中,我们介绍了Redis可能会根据环境或用户指定选择不同的内存管理库.在linux系统中,Redis默认使用jemalloc库.当然用户可以指定 ...

  5. Redis源码解析——前言

    今天开启Redis源码的阅读之旅.对于一些没有接触过开源代码分析的同学来说,可能这是一件很麻烦的事.但是我总觉得做一件事,不管有多大多难,我们首先要在战略上蔑视它,但是要在战术上重视它.除了一些高大上 ...

  6. Redis源码解析(15) 哨兵机制[2] 信息同步与TILT模式

    Redis源码解析(1) 动态字符串与链表 Redis源码解析(2) 字典与迭代器 Redis源码解析(3) 跳跃表 Redis源码解析(4) 整数集合 Redis源码解析(5) 压缩列表 Redis ...

  7. Redis源码解析——Zipmap

    本文介绍的是Redis中Zipmap的原理和实现.(转载请指明出于breaksoftware的csdn博客) 基础结构 Zipmap是为了实现保存Pair(String,String)数据的结构,该结 ...

  8. Redis源码解析——有序整数集

    有序整数集是Redis源码中一个以大尾(big endian)形式存储,由小到大排列且无重复的整型集合.它存储的类型包括16位.32位和64位的整型数.在介绍这个库的实现前,我们还需要先熟悉下大小尾内 ...

  9. Redis源码解析——字典结构

    C++语言中有标准的字典库,我们可以通过pair(key,value)的形式存储数据.但是C语言中没有这种的库,于是就需要自己实现.本文讲解的就是Redis源码中的字典库的实现方法.(转载请指明出于b ...

  10. Redis源码解析——字典遍历

    之前两篇博文讲解了字典库的基础,本文将讲解其遍历操作.之所以将遍历操作独立成一文来讲,是因为其中的内容和之前的基本操作还是有区别的.特别是高级遍历一节介绍的内容,充满了精妙设计的算法智慧.(转载请指明 ...

最新文章

  1. GraphViz:2 DOT语法和相关应用
  2. Python 的AES加密与解密
  3. 微信 小程序 canvas
  4. java中间件是什么意思_数据库中间件漫谈
  5. spring data redis的使用jar包版本冲突问题
  6. [收藏]Mysql日期和时间函数
  7. 将excel中的数据导入到oracle数据库中
  8. 别了MongoDB?
  9. 推荐软件——total commander(善用佳软)
  10. html青蛙跳跳游戏,《小青蛙跳跳》小班游戏教案
  11. 面向数字孪生城市的智能化全息测绘(论文摘抄)
  12. 新公司入职 从零开始搭建环境
  13. 修改手机状态栏字体的颜色(如:白底黑字)
  14. 大数据案例--电信日志分析系统
  15. linux 内存耗尽重启,【server故障】linux下JVM内存耗尽故障
  16. 现在还能买什么股票呢?
  17. C语言中常见的转义字符总结
  18. 泰森多面体Voronoi 3D-V5.0 功能介绍
  19. 【蓝桥杯程序设计大赛感想】 一路艰辛 一路收获
  20. PV操作详解(附详细例题解析和总结)

热门文章

  1. EntityFramework Core映射关系详解
  2. 20145209 2016-2017-2 《Java程序设计》第9周学习总结
  3. DIV+CSS_1_样式表的分类
  4. 在webLogic 10.3中部署Hibernate 3.5出现 ClassNotFoundException解决办法
  5. 超过3000赞的「机器学习路线图」,教你升级打怪全攻略
  6. 互联网“高薪榜”曝光,物联网将接棒?
  7. 飞鸽传书下载最新版2013
  8. 今天的一条条平坦的即时通讯
  9. 并且确定已经识别出了主要的HTML5技术风险
  10. 一个DirectSound的例子