Redis,对于大家来说应该不陌生,是经常使用的开发技术之一。原始的RDBMS关系型数据库,能够存储海量的数据,但是在某些特殊的情况下,性能并不是特别的好,例如热点数据的读写,数据缓存等。Redis作为NoSQL中的一员,基于内存数据存储,支持多种数据结构,单线程处理,是一款高性能的可持久化key-value数据库。对于Redis就不做过多介绍了,相信大家或多或少都了解过,下面重点描述SpringBoot如何与Redis进行整合,若是大神,请一笑而过。
还是和之前一样,我们先来搭建项目,先学会如何使用,再来具体了解其中的内容和原理。
项目版本:SpringBoot (2.1.4)
首先,引入redis依赖:
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.6.1
根据版本的不一致,引入方式可能不一样,若导入失败,请使用spring-boot-starter-redis。
application.properties:
#redis地址
spring.redis.host=192.168.159.129
#redis客户端lettuce配置
#最大连接数,负数表示无限制
spring.redis.lettuce.pool.max-active=8
#最大等待,负数表示无限制
spring.redis.lettuce.pool.max-wait=-1
#shutdown超时
spring.redis.lettuce.shutdown-timeout=100
#最大空闲连接数,负数表示无限制
spring.redis.lettuce.pool.max-idle=8
#最小空闲连接数
spring.redis.lettuce.pool.min-idle=0
更多配置信息,后文继续讲解。
启动类SpringbootRedisApplication:
@SpringBootApplication
@RestController
public class SpringbootRedisApplication {
/**
* 注入StringRedisTemplate
*/
private final StringRedisTemplate stringRedisTemplate;
@Autowired
public SpringbootRedisApplication(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
public static void main(String[] args) {
SpringApplication.run(SpringbootRedisApplication.class, args);
}
@GetMapping("/name")
public String get(){
this.stringRedisTemplate.opsForValue().set("name","英雄");
return this.stringRedisTemplate.opsForValue().get("name");
}
}
这是最简单的redis集成,大家可以发现我们没有创建RedisConnectionFactory、Pool等相关的XML或者注解信息,就能很好的供大家使用。其中的原理,相信大家已经了解,这是SpringBoot自动进行配置了,至于是如何配置的,后文继续。在这里,我先为大家介绍两个重要的类。
使用过Spring Data Redis的都知道,RedisTemplete和StringRedisTemplete是Spring Data为我们封装好的两种操作redis模板,使用它们,我们可以无需关注数据序列化和连接管理,使用户更加关注核心业务,减少connection 未close等问题。
RedisTemplete是操作redis命令的核心类,提供了丰富的API供大家使用,并且是线程安全的。我们可以发现,RedisTemplete提供了操作redis命令的Operations,大家都知道Redis支持多种数据类型,例如:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。RedisTemplete也针对redis的数据结构提供了多种类型的Operations。部分功能如下:
//键值对存储
this.redisTemplate.opsForValue().set("name","张三");
String name = (String)this.redisTemplate.opsForValue().get("name");
log.info(name);
//list存储
this.redisTemplate.opsForList().leftPushAll("names","李四","王五","赵六");
List names = this.redisTemplate.opsForList().range("names", 0, 3);
log.info(names.toString());
//hash使用
Map map = new HashMap<>(4);
map.put("name","秦始皇");
map.put("age","未知");
map.put("sex","男");
this.redisTemplate.opsForHash().putAll("HASH_PERSON",map);
String s =(String) this.redisTemplate.opsForHash().get("HASH_PERSON", "name");
log.info(s);
当然,RedisTemplete的功能不仅仅如此,除了提供各种类型的Operations之外,还能通过它设置序列化方式,默认采用的是Jdk序列化方式JdkSerializationRedisSerializer,其它的功能需要大家慢慢探索,就不一 一展示了。在使用RedisTemplete的过程中需要注意,不支持键为null,不然会抛出java.lang.IllegalArgumentException: non null key required异常,value可以为null,在使用时键可以为空字符串,但是不建议大家这样使用。在使用的过程中,如果大家想要使用自定义或者其它序列化方式,可以自动注入RedisTemplete,例如:
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate redisTemplate = new RedisTemplate<>();
//针对key设置StringRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
//针对value设置Jackson2JsonRedisSerializer
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
在项目中,key和value基本上都是String类型的数据,为了方便大家开发,又提供了StringRedisTemplete供大家使用。StringRedisTemplete是RedisTemplete的子类,采用StringRedisSerializer进行序列化。这里就不做过多介绍了,StringRedisTemplete只是RedisTemplete
上面的内容是使用SpringDataRedis模块的基础,众所周知,SpringBoot会自动配置Starter Poms依赖的相关内容,下面我们就来探讨探讨。
首先,我们需要找到redis的自动配置类。在使用SpringBoot的时候,会自动引入spring-boot-autoconfigure的依赖,从该依赖的spring.factories中,我们可以找到所有自动配置类的位置,搜索redis,找到自动配置类RedisAutoConfiguration。
RedisAutoConfiguration.java:
需要RedisOperations类,该类指定了一系列Redis操作,由RedisTemplete实现
redis的配置从RedisProperties中获取
导入LettuceConnectionConfiguration、JedisConnectionConfiguration两种配置 对应Lettuce、jedis两种集成
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
/**
* 若上下文不存在RedisTemplete Bean
* 注入RedisTemplete Bean供开发使用
*/
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate
从中,我们发现Redis自动配置,支持使用Lettuce、jedis两种客户端操作。针对两种操作,SpringBoot提供了两套Redis连接配置LettuceConnectionConfiguration、JedisConnectionConfiguration。默认使用Lettuce客户端进行操作,若大家想要使用Jedis进行操作,也是可以的,如下:
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
在进行自动配置时,Redis的配置信息按照如下方式获取:
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
//默认数据库
private int database = 0;
//采用url进行配置,例如:redis://user:[email protected]:6379
private String url;
//redis服务的地址
private String host = "localhost";
//密码
private String password;
//端口
private int port = 6379;
//是否开启SSL
private boolean ssl;
//连接超时
private Duration timeout;
//哨兵模式配置
private Sentinel sentinel;
//集群模式配置
private Cluster cluster;
//支持Jedis配置
private final Jedis jedis = new Jedis();
//支持Lettuce配置
private final Lettuce lettuce = new Lettuce();
/**
* 连接池配置
*/
public static class Pool {
//最大空闲连接,若为负数表示没有限制
private int maxIdle = 8;
//最小空闲连接
private int minIdle = 0;
//最大使用连接,若为负数表示没有限制
private int maxActive = 8;
//获取连接最大等待时间,-1代表永久等待
private Duration maxWait = Duration.ofMillis(-1);
}
/**
* 集群配置
*/
public static class Cluster {
//集群节点列表
private List nodes;
//集群支持的最大重定向数
private Integer maxRedirects;
}
/**
* 哨兵模式配置
*/
public static class Sentinel {
// 哨兵服务名
private String master;
// 节点配置
private List nodes;
}
/**
* jedis客户端配置
*/
public static class Jedis {
private Pool pool;
}
/**
* Lettuce客户端配置
*/
public static class Lettuce {
private Duration shutdownTimeout = Duration.ofMillis(100);
private Pool pool;
}
}
LettuceConnectionConfiguration部分内容(Lettuce连接工厂):
/**
* 若上下文不存在RedisConnectionFactory Bean
* 则进行实例化
*/
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public LettuceConnectionFactory redisConnectionFactory(
ClientResources clientResources) throws UnknownHostException {
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(
clientResources, this.properties.getLettuce().getPool());
return createLettuceConnectionFactory(clientConfig);
}
private LettuceConnectionFactory createLettuceConnectionFactory(
LettuceClientConfiguration clientConfiguration) {
//若为哨兵模式,使用哨兵模式创建连接工厂
if (getSentinelConfig() != null) {
return new LettuceConnectionFactory(getSentinelConfig(), clientConfiguration);
}
//若为集群模式,使用集群模式创建连接工厂
if (getClusterConfiguration() != null) {
return new LettuceConnectionFactory(getClusterConfiguration(),
clientConfiguration);
}
//使用单节点模式创建连接工厂
return new LettuceConnectionFactory(getStandaloneConfig(), clientConfiguration);
}
本文主要讲述springboot与redis整合的基础内容以及redis的一些使用方式,大家可以自行编码测试相关内容。若有不对的地方,望大家指正,共同进步,谢谢。
源码:https://gitee.com/hpaw/SpringBoot2Demo/tree/master/springboot-redis