框架編程-spring-redisTemplate訪問多數據源實現

背景

在使用spring boot 2.x做項目的時候,需要訪問多個數據庫db,本博客講進行實戰展示

實戰

思路:每一個redisTemplate實例只能訪問一個對應的db,所以我們需要做多個redisTemplate實例,並且每個實例必須有自己對應的連接工廠。

package com.ztjy.contentrank.common;

import com.alibaba.fastjson.parser.ParserConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ztjy.parent.redis.FastJson2JsonRedisSerializer;
import com.ztjy.parent.redis.RedisProperties;
import com.ztjy.tool.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisPassword;
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.StringRedisSerializer;
import java.time.Duration;

@Log4j2
@SuppressWarnings("unchecked")
public class MyRedisAutoConfiguration {
    @Autowired
    private MyServerProperties myServerProperties;
    @Autowired
    private RedisProperties redisProperties;

    static {
        ParserConfig.getGlobalInstance().addAccept("com.xxxx");
    }

    private RedisTemplate redisTemplateMaker(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);

        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
        FastJson2JsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJson2JsonRedisSerializer<>(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        fastJsonRedisSerializer.setObjectMapper(mapper);

        //使用StringRedisSerializer來序列化和反序列化redis的key值
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean(name = "recallRedisTemplate")
    public RedisTemplate recallRedisTemplate(@Qualifier(value = "recallLettuceConnectionFactory") LettuceConnectionFactory recallLettuceConnectionFactory) {
        return redisTemplateMaker(recallLettuceConnectionFactory);
    }

    @Bean(name = "portraitRedisTemplate")
    public RedisTemplate portraitRedisTemplate(@Qualifier(value = "portraitLettuceConnectionFactory") LettuceConnectionFactory portraitLettuceConnectionFactory) {
        return redisTemplateMaker(portraitLettuceConnectionFactory);
    }


    @Bean(value = "recallLettuceConnectionFactory")
    @Primary
    public LettuceConnectionFactory recallLettuceConnectionFactory(
            @Qualifier(value = "genericObjectPoolConfig") GenericObjectPoolConfig genericObjectPoolConfig) {
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration
                .builder()
                .commandTimeout(Duration.ofMillis(this.redisProperties.getTimeout()))
                .poolConfig(genericObjectPoolConfig)
                .build();
        return new LettuceConnectionFactory(redisStandaloneConfiguration(myServerProperties.getRedis().getRecallDb()), clientConfig);
    }

    @Bean(value = "portraitLettuceConnectionFactory")
    public LettuceConnectionFactory portraitLettuceConnectionFactory(
            @Qualifier(value = "genericObjectPoolConfig") GenericObjectPoolConfig genericObjectPoolConfig) {
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration
                .builder()
                .commandTimeout(Duration.ofMillis(this.redisProperties.getTimeout()))
                .poolConfig(genericObjectPoolConfig)
                .build();
        return new LettuceConnectionFactory(redisStandaloneConfiguration(myServerProperties.getRedis().getPortraitDb()), clientConfig);
    }

    private RedisStandaloneConfiguration redisStandaloneConfiguration(int db) {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisProperties.getHost());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            config.setPassword(RedisPassword.of(redisProperties.getPassword()));
        }
        config.setPort(redisProperties.getPort());
        config.setDatabase(db);
        return config;
    }
}

在使用的時候,只需要注入對應名稱的redisTemplate就可以了。

@Autowired
@Qualifier(value = "recallRedisTemplate")
private RedisTemplate recallRedisTemplate;
@Autowired
@Qualifier(value = "portraitRedisTemplate")
private RedisTemplate portraitRedisTemplate;

評價

注意:

  • 主工廠bean需要添加@primary
  • 每個redisTemplate需要有自己對應的工廠bean來設置對應的db
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章