redis实现多数据源思路
1、先了解单数据源配置
在org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE包下面的 org.springframework.boot.autoconfigure.data.redis这个包下面的 RedisAutoConfiguration 类中,会自动配置。
(1)springboot自动配置redis类
@Configuration(proxyBeanMethods = false)//标志这是一个配置类,proxyBeanMethods=false表示,不管你怎么调用里面的bean,都永远是一个实例,默认为true
@ConditionalOnClass(RedisOperations.class)//
@EnableConfigurationProperties(RedisProperties.class)
//给容器导入LettuceConnectionConfiguration,JedisConnectionConfiguration这2个配置
//需要明白,这2个配置到底起不起作用,还得具体根据配置类上面的配置信息来讲。原理跟RedisAutoConfiguration类
//上面的配置信息时一样的
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
}
-
说明1
当引入了下面的依赖的时候RedisOperations这个类就存在了。也就是说
@ConditionalOnClass(RedisOperations.class)这句话起作用了,为true,下面配置类才会起作用。
注意:如果有多条件的时候,需要所有条件都为true的时候,配置类才会起作用。这个是springboot的核心思想
<!--集成redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
-
说明2
@EnableConfigurationProperties(RedisProperties.class)
启用这个配置类RedisProperties
相当于把RedisProperties这个配置类通过bean的方式加入到spring容器,
也可以直接在这个类上面RedisProperties加入注解@Component,把这个类加载到spring容器中。
这个主要的目的就是为了便于其他地方可以直接通过bean注入的方式使用bean里面的属性。【思想】
(2)自动配置了
引用至:http://springboot.javaboy.org/2019/0603/springboot-redis 江南一点雨
自定义配置类
###不用默认的配置,使用自己定义的配置
/**
* redis配置,默认情况下,引入了redis的starter不用配置为什么。
* 在org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE包下面的
* org.springframework.boot.autoconfigure.data.redis这个包下面的
* RedisAutoConfiguration类中,会自动配置
* 1、配置类需要配置哪些东西,以什么开头的呢?
* RedisProperties 查看配置类以spring.redis开头
* 2、配置了哪些
* redisTemplate-bean
* stringRedisTemplate-bean
* 加入说要替换怎么做
* --默认存储值的序列化方式为
* @see RedisSerializer.json()
*/
@Configuration(value = "redisConfigConfiguration")
@AllArgsConstructor
public class RedisConfig {
/**
* 定制化自己的redisTemplate
* --@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
* 导入进来的
*/
private final RedisConnectionFactory connectionFactory;
/**
* 观察相关值的序列化RedisSerializer接口
* setKeySerializer(RedisSerializer.string());
* setValueSerializer(RedisSerializer.string());
* setHashKeySerializer(RedisSerializer.string());
* setHashValueSerializer(RedisSerializer.string());
* 序列化方式
* 1、string RedisSerializer.string() --StringRedisSerializer
* 2、json RedisSerializer.json() --GenericJackson2JsonRedisSerializer
* 3、java RedisSerializer.java() --JdkSerializationRedisSerializer
* 4、byteArray RedisSerializer.byteArray() --ByteArrayRedisSerializer.INSTANCE
*/
/**
* 配置KeySerializer
*/
@ConditionalOnMissingBean(name = "javaRedisTemplate")
@Primary
@Bean("javaRedisTemplate")
public RedisTemplate<String, Object> javaRedisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
@ConditionalOnMissingBean(name = "jsonRedisTemplate")
@Bean("jsonRedisTemplate")
public RedisTemplate<String, Object> jsonRedisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(RedisSerializer.json());
redisTemplate.setHashValueSerializer(RedisSerializer.json());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
- 说明
如果要使用RedisSerializer.json(),需要额外引入jackson的依赖
<!--如果使用了lettuce连接池,需要额外导入包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--配置jsonRedisTemplate使用RedisSerializer.json()-->
<!--com/fasterxml/jackson/core/JsonProcessingException异常,额外使用了fasterxml包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
redis使用
@SpringBootApplication
public class RedisRunMain {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(RedisRunMain.class, args);
ConfigurableListableBeanFactory beanFactory = run.getBeanFactory();
System.out.println("beanDefinitionName=======start");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println("容器中定义beanName名称:" + beanDefinitionName);
}
RedisStandaloneConfiguration redisConfig = (RedisStandaloneConfiguration)beanFactory.getBean("redisConfig");
System.out.println(JSONUtil.toJsonStr(redisConfig));
System.out.println("beanDefinitionName=======end");
RedisTemplate stringRedisTemplate = (RedisTemplate) beanFactory.getBean("redisTemplate2");
//使用就在这
stringRedisTemplate.opsForValue().set("com:wolf:boy:zw:stringRedisTemplate", "initValue", Duration.ofMinutes(30));
}
public static void t1(ConfigurableListableBeanFactory beanFactory){
RedisTemplate redisTemplate = (RedisTemplate) beanFactory.getBean("redisTemplate");
redisTemplate.opsForValue().set("com:wolf:boy:zw", "initValue", Duration.ofMinutes(30));
//在看看用stringRedisTemplate
RedisTemplate stringRedisTemplate = (RedisTemplate) beanFactory.getBean("stringRedisTemplate");
stringRedisTemplate.opsForValue().set("com:wolf:boy:zw:stringRedisTemplate", "initValue", Duration.ofMinutes(30));
}
}
redis单数据源搞定了,多数据源如何配置呢
yml配置
spring:
redis:
host: redis连接ip
port: 6392
password: Zp7VCeVL
database: 1 #默认连接的数据库是0,可以改成其他的
##连接池【使用lettuce连接池】--spring-boot-starter-data-redis自带的
lettuce:
pool:
##最大连接数
max-active: 8
#最大和最小空闲连接
max-idle: 4
min-idle: 0
##连接的最大等待阻塞的时间
max-wait: 10000
redis2:
host: redis连接ip
port: 6392
password: Zp7VCeVL
database: 2 #默认连接的数据库是0,可以改成其他的
- 说明1
spring.redis.xxx后面的属性配置,是springboot底层自动配置属性类
RedisProperties的属性信息,也就是说你配置了这个配置,什么都不用干,springboot底层默认给你配置好了的。
这就是所谓的约定大于配置。开箱即用
- 说明2
要配置多数据源,原理很简单
#1、redis连接信息配置(多份)
--yml配置好了,需要创建对应的属性类去接收这些属性
#2、代码配置连接工厂(多份)
LettuceConnectionFactory 我这是基于Lettuce的,也可以基于Jedis
#3、创建RedisTemplate实例(多份)
原则,为什么是上面这些步骤。
(1)在创建RedisTemplate的时候
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(RedisSerializer.json());
redisTemplate.setHashValueSerializer(RedisSerializer.json());
redisTemplate.setConnectionFactory(connectionFactory);//看着核心【需要提供一个RedisConnectionFactory】
#RedisConnectionFactory redis连接工厂,这个啥意思,说白了就是连接redis数据库所需的账号啊,密码,什么的都是由这个工厂
掌握,但是具体到底用哪个,还是那句话,看需要。redis连接池最好的就是Lettuce和Jedis
LettuceConnectionFactory
JedisConnectionFactory
#到此,创建RedisTemplate需要RedisConnectionFactory,那我们的想方设法的创建一个RedisConnectionFactory实例。
#创建LettuceConnectionFactory
@Bean
public LettuceConnectionFactory factory(GenericObjectPoolConfig config,
RedisStandaloneConfiguration redisConfig) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
return new LettuceConnectionFactory(redisConfig, clientConfiguration);
}
##创建JedisConnectionFactory
public RedisConnectionFactory getRedisConnectionFactory(String hostName,
String password, int port, int maxActive, int maxIdle, int minIdle,
long maxWait, int database) { // 是负责建立Factory的连接工厂类
JedisConnectionFactory jedisFactory = new JedisConnectionFactory();
jedisFactory.setHostName(hostName);
jedisFactory.setPort(port);
jedisFactory.setPassword(password);
jedisFactory.setDatabase(database);
JedisPoolConfig poolConfig = new JedisPoolConfig(); // 进行连接池配置
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWait);
jedisFactory.setPoolConfig(poolConfig);
jedisFactory.afterPropertiesSet(); // 初始化连接池配置
return jedisFactory;
}
完整代码(参考)实际根据自己的需要编写
@Configuration
@EnableConfigurationProperties(RedisPropertiesTwo.class)
public class RedisConfigTwo {
/**
* 配置lettuce连接池
* 【这个是连接池的通用配置,搞一份就好了】
* @return
*/
@Bean
@ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
public GenericObjectPoolConfig redisPool() {
return new GenericObjectPoolConfig<>();
}
//这个配置类,静态内部类,主要就是做配置用的
@Configuration
//相当于把RedisPropertiesOne配置类加入到spring容器,并且完成了yml的属性与类属性的绑定
@EnableConfigurationProperties(RedisPropertiesOne.class)
static class Config {
/**
* 配置第一个数据源的
*
* @return
*/
@Bean
public RedisStandaloneConfiguration redisConfig(RedisPropertiesOne redisPropertiesOne) {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(redisPropertiesOne.getHost());
config.setPort(redisPropertiesOne.getPort());
config.setPassword(RedisPassword.of(redisPropertiesOne.getPassword()));
config.setDatabase(redisPropertiesOne.getDatabase());
return config;
}
/**
* 配置第二个数据源
*
* @return
*/
@Bean
public RedisStandaloneConfiguration redisConfig2(RedisPropertiesTwo redisPropertiesTwo) {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(redisPropertiesTwo.getHost());
config.setPort(redisPropertiesTwo.getPort());
config.setPassword(RedisPassword.of(redisPropertiesTwo.getPassword()));
config.setDatabase(redisPropertiesTwo.getDatabase());
return config;
}
}
/**
* 配置第一个数据源的连接工厂
* 这里注意:需要添加@Primary 指定bean的名称,目的是为了创建两个不同名称的LettuceConnectionFactory
*
* @param config
* @param redisConfig
* @return
*/
@Bean("factory")
@Primary
public LettuceConnectionFactory factory(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
return new LettuceConnectionFactory(redisConfig, clientConfiguration);
}
@Bean("factory2")
public LettuceConnectionFactory factory2(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig2) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
return new LettuceConnectionFactory(redisConfig2, clientConfiguration);
}
/**
* 配置第一个数据源的RedisTemplate
* 注意:这里指定使用名称=factory 的 RedisConnectionFactory
* 并且标识第一个数据源是默认数据源 @Primary
*
* @param factory
* @return
*/
@ConditionalOnMissingBean(name = "redisTemplate")
@Bean("redisTemplate")
@Primary
public RedisTemplate<String, String> redisTemplate(@Qualifier("factory") RedisConnectionFactory factory) {
return getStringStringRedisTemplate(factory);
}
/**
* 配置第一个数据源的RedisTemplate
* 注意:这里指定使用名称=factory2 的 RedisConnectionFactory
*
* @param factory2
* @return
*/
@ConditionalOnMissingBean(name = "redisTemplate2")
@Bean("redisTemplate2")
public RedisTemplate<String, String> redisTemplate2(@Qualifier("factory2") RedisConnectionFactory factory2) {
return new StringRedisTemplate(factory2);
}
}
#配置类代码
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedisPropertiesOne {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Connection URL. Overrides host, port, and password. User is ignored. Example:
* redis://user:password@example.com:6379
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
}
#2
@ConfigurationProperties(prefix = "spring.redis2")
@Data
public class RedisPropertiesTwo {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Connection URL. Overrides host, port, and password. User is ignored. Example:
* redis://user:password@example.com:6379
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
}
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-boot-group</artifactId>
<groupId>com.wolf.boy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-redis-one</artifactId>
<dependencies>
<!--集成redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--如果使用了lettuce连接池,需要额外导入包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--配置jsonRedisTemplate使用RedisSerializer.json()-->
<!--com/fasterxml/jackson/core/JsonProcessingException异常,额外使用了fasterxml包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
参考:
https://www.fangzhipeng.com/springboot/2017/05/09/sb9-redis.html