在redis中绿渣,一個實例,默認有16個庫燕耿,數據庫名以序號命名0~15中符,可以根據業(yè)務需要的不同,把數據存儲在不同序號的數據中誉帅。在實際應用中淀散,該如何寫配置文件,才能連接多個redis數據源呢蚜锨,今天就來試一試档插。
在使用Redis之前,首先需要安裝Redis數據庫亚再,沒安裝的可以參考SpringBoot初次集成Redis踩坑郭膛,安裝+使用 一文,這里就不細說Redis的安裝了氛悬。
本文基于SpringBoot2.1.4對Redis多數據源進行集成的则剃。在集成的過程中用到了jedis client、Apache的commons-pool2如捅、jackson-databind棍现,以及spring-boot-starter-data-redis,在pom中需要把這些必須的架包引入镜遣;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
第二步己肮,配置文件的配置;
import java.io.Serializable;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* redis配置類
* @author 程就人生
* @date 2019年12月16日
*/
@Configuration
@EnableCaching//開啟注解式緩存
public class RedisMoreDatasourceConfig extends CachingConfigurerSupport {
/**
* 配置lettuce連接池(多數據源的公共參數)
* GenericObjectPoolConfig不是線程安全的
* @return
*/
@SuppressWarnings("rawtypes")
@Bean
@ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
public GenericObjectPoolConfig redisPool() {
return new GenericObjectPoolConfig<>();
}
/**
* 配置第一個數據源的
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = "spring.redis")
public RedisStandaloneConfiguration redisConfig() {
return new RedisStandaloneConfiguration();
}
/**
* 配置第二個數據源
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = "spring.redis2")
public RedisStandaloneConfiguration redisConfig2() {
return new RedisStandaloneConfiguration();
}
/**
* 配置第一個數據源的連接工廠
* 這里注意:需要添加@Primary 指定bean的名稱,目的是為了創(chuàng)建兩個不同名稱的LettuceConnectionFactory
*
* @param config
* @param redisConfig
* @return
*/
@SuppressWarnings("rawtypes")
@Bean("factory")
@Primary
public LettuceConnectionFactory factory(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
return new LettuceConnectionFactory(redisConfig, clientConfiguration);
}
@SuppressWarnings("rawtypes")
@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
*/
@Bean("redisTemplate")
@Primary
public RedisTemplate<Serializable, Serializable> redisTemplate(@Qualifier("factory") RedisConnectionFactory factory) {
RedisTemplate<Serializable, Serializable> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new JdkSerializationRedisSerializer());
//開啟事務
template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
/**
* 配置第一個數據源的RedisTemplate
* 注意:這里指定使用名稱=factory2 的 RedisConnectionFactory
*
* @param factory2
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean("redisTemplate2")
public RedisTemplate<String, Object> redisTemplate2(@Qualifier("factory2") RedisConnectionFactory factory2) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory2);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
第三步朴肺,properties文件里也需要對應的參數窖剑;
#Redis common param
spring.redis.lettuce.pool.max-idle=100
spring.redis.lettuce.pool.min-idle=50
spring.redis.lettuce.pool.max-wait=2000
cache.default-exp=72
#data 0
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=3000
#data 1
spring.redis2.database=1
spring.redis2.host=127.0.0.1
spring.redis2.port=6379
spring.redis2.password=
spring.redis2.timeout=3000
第四步,測試代碼戈稿;
import com.alibaba.fastjson.JSONObject;
@RestController
public class IndexController {
/**
* 第一個數據源對應的template
*/
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 第二個數據源對應的template
*/
@Autowired
@Qualifier("redisTemplate2")
private RedisTemplate<String, Object> redisTemplate2;
//測試
@GetMapping("/index")
public void index(){
//數據庫0西土,數據的存儲及取出
redisTemplate.opsForValue().set("aa", "aaaaa");
String aa = (String) redisTemplate.opsForValue().get("aa");
System.out.println(aa);
//數據庫1,數據的存儲及取出
JSONObject json = new JSONObject();
json.put("aa", "bbbbbb");
redisTemplate2.opsForHash().put("cc", "aa", json);
json = (JSONObject) redisTemplate2.opsForHash().get("cc", "aa");
System.out.println(json.toJSONString());
}
}
最后鞍盗,測試需了;啟動入口程序,在瀏覽器上輸出Controller的地址般甲,從控制臺可以看到測試的結果肋乍;
為了保險起見,還是去客戶端查看一下存儲的結果吧敷存。
在做這個demo時墓造,遇到了一些問題及總結;
- 把配置文件的類名命名為RedisConfig锚烦,在項目啟動時會報bean名重復觅闽,這是因為和配置文件里的bean名重復了,這是需要注意的地方涮俄;
- 在RedisStandaloneConfiguration類中蛉拙,默認的host是localhost,port是6379彻亲,database默認的是0孕锄,password默認無,這些都可以通過RedisStandaloneConfiguration的源碼找到苞尝,在配置文件里沒有時畸肆,就會使用默認的參數;
- 在RedisConnectionFactory接口里宙址,getConnection()有兩種實現方式轴脐,一種是JedisConnectionFactory,一種是LettuceConnectionFactory曼氛,本文的示例中使用的是后一種豁辉,這個可以根據個人喜好進行選擇令野;
- 不管有幾個數據源舀患,最好配置一個@Primary數據源;在使用RedisTemplate時气破,如果不用@Qualifier注解指明聊浅,則使用默認的數據源。