使用环境:springboot 2.0.0 redis 哨兵
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">
<groupId>com.chainhu.demo</groupId>
<artifactId>demo</artifactId>
<packaging>pom</packaging>
<modules>
<module>DemoTest1</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
</dependencies>
</project>
配置文件如下:application.properties
# Redis Pool Config
redis.maxTotal=8
redis.maxIdle=8
redis.minIdle=1
redis.maxWaitMillis=5000
redis.minEvictableIdleTimeMillis=300000
redis.numTestsPerEvictionRun=3
redis.timeBetweenEvictionRunsMillis=60000
# Redis Sentinel Config
redis.database={"host": [0, 1]}
redis.clientName={"host": "client_name"}
redis.sentinel.masterName={"host": "master_name"}
redis.sentinel={"host": ["192.168.116.130:26379", "192.168.116.130:26380", "192.168.116.130:26381"]}
redis.connectionTimeout=1000
redis.soTimeout=2000
redis.password={"host": "12345"}
动态创建bean类:DynamicRedisSource.java
package com.chainhu.demo;
import com.alibaba.fastjson.JSON;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author huzhengyao
* 自动创建多个jedisSentinelPool
* @date 2018/9/5
*/
@Configuration
public class DynamicRedisSource {
@Autowired
private Environment env;
@Autowired
private ApplicationContext applicationContext;
@Bean
public Object dynamicCreateRedisPool() throws Exception {
ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
/**
* 设置属性
*/
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(1);
jedisPoolConfig.setMaxTotal(Integer.parseInt(env.getProperty("redis.maxTotal")));
jedisPoolConfig.setMaxIdle(Integer.parseInt(env.getProperty("redis.maxIdle")));
jedisPoolConfig.setMaxWaitMillis(Integer.parseInt(env.getProperty("redis.maxWaitMillis")));
jedisPoolConfig.setMinIdle(Integer.parseInt(env.getProperty("redis.minIdle")));
jedisPoolConfig.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("redis.minEvictableIdleTimeMillis")));
jedisPoolConfig.setNumTestsPerEvictionRun(Integer.parseInt(env.getProperty("redis.numTestsPerEvictionRun")));
jedisPoolConfig.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("redis.timeBetweenEvictionRunsMillis")));
final GenericObjectPoolConfig poolConfig = jedisPoolConfig;
final Integer connectionTimeout = Integer.parseInt(env.getProperty("redis.connectionTimeout"));
final Integer soTimeout = Integer.parseInt(env.getProperty("redis.soTimeout"));
Map uriMap = JSON.parseObject(env.getProperty("redis.sentinel"));
Map dbMap = JSON.parseObject(env.getProperty("redis.database"));
Map pwdMap = JSON.parseObject(env.getProperty("redis.password"));
Map clientNameMap = JSON.parseObject(env.getProperty("redis.clientName"));
Map masterNameMap = JSON.parseObject(env.getProperty("redis.sentinel.masterName"));
for (Object key: uriMap.keySet()){
Set<String> sentinels = new HashSet<>();
List<String> uriList = (List<String>) uriMap.get(key);
for (String uri: uriList){
sentinels.add(uri);
}
final String clientName = (String) clientNameMap.get(key);
String masterName = (String) masterNameMap.get(key);
String pwd = (String) pwdMap.get(key);
List<Integer> dbs = (List<Integer>) dbMap.get(key);
for (final Integer db: dbs){
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(JedisSentinelPool.class);
/**
* 设置构造函数参数
*/
beanDefinitionBuilder.addConstructorArgValue(masterName);
beanDefinitionBuilder.addConstructorArgValue(sentinels);
beanDefinitionBuilder.addConstructorArgValue(poolConfig);
beanDefinitionBuilder.addConstructorArgValue(connectionTimeout);
beanDefinitionBuilder.addConstructorArgValue(soTimeout);
beanDefinitionBuilder.addConstructorArgValue(pwd);
beanDefinitionBuilder.addConstructorArgValue(db);
beanDefinitionBuilder.addConstructorArgValue(clientName);
/**
* 注册到spring容器中
*/
beanFactory.registerBeanDefinition("jedisSentinelPool" + db, beanDefinitionBuilder.getBeanDefinition());
}
}
return null;
}
}
使用:
创建一个单元测试类:DynamicTest.class
package com.chainhu.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
/**
* @author huzhengyao
* @date 2018/9/5
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DynamicTest {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private JedisSentinelPool jedisSentinelPool0;
@Autowired
private JedisSentinelPool jedisSentinelPool1;
@Test
public void test(){
Jedis jedis = jedisSentinelPool0.getResource();
String value = jedis.get("PRODUCT_123");
System.out.println(value);
jedis.close();
Jedis jedis1 = jedisSentinelPool1.getResource();
String set = jedis1.get("ORDER_123");
System.out.println(set);
jedis1.close();
}
}
登陆redis: 查看当前redis 0库和1库中对应得PRODUCT_123 和ORDER_123 对应得值:
运行单元测试类查看结果, 如下:
动态创建两个jedisSentinelPool成功。
本文主要用到了spring ioc, 通过ListableBeanFactory实现bean的注册。