springboot自定义RedisTemplate并使用jedis配置连接池

使用Jedis线程池可以不需要创建新的Jedis对象连接Redis,可以大大减少对于创建和回收Redis连接的开销

@Primary: 当出现相同名字的bean是,优先使用使用了 @Primary 注解的bean

下面开始使用:

1、第一步我们需要导入相应的jar包
<!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
<!--     Redis连接Java工具 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
2、在application.yaml里配置我们想要的配置
redis:
  # 可配置参数:https://www.bbsmax.com/A/x9J2RXbMJ6/
  #地址
  host: 127.0.0.1
  #端口号
  port: 6379
  database: 0
  #如果有密码,请填写
  password:
  #连接超时时间
  timeout: 3000
  #最大空闲连接数
  maxIdle: 200
  #最大连接数(空闲+等待)
  maxTotal: 500
  #最大建立连接等待时间。如果超时抛出异常。设为-1表示无限制。
  maxWaitMillis: 1000
  #连接多久没有使用设置为闲置,检测线程直接剔除闲置
  minEvictableIdleTimeMillis: 300000

  #每次释放连接的最大数目,默认3
  numTestsPerEvictionRun: 1024
  #   后台检测线程周期 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
  timeBetweenEvictionRunsMillis: 30000
  #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
  testOnBorrow: true
  #后台线程对idle连接进行扫描,检测是否有效
  testWhileIdle: true
3、我们需要创建一个RedisConfig配置的Java文件,读取我们配置的参数
@Configuration
public class RedisConfig {

    @Value("${redis.host}")
    private String host;

    @Value("${redis.port}")
    private Integer port;

    @Value("${redis.database}")
    private Integer database;

    @Value("${redis.password}")
    private String password;

    @Value("${redis.timeout}")
    private Integer timeout;

    @Value("${redis.maxIdle}")
    private Integer maxIdle;

    @Value("${redis.maxTotal}")
    private Integer maxTotal;

    @Value("${redis.maxWaitMillis}")
    private Integer maxWaitMillis;

    @Value("${redis.minEvictableIdleTimeMillis}")
    private Integer minEvictableIdleTimeMillis;

    @Value("${redis.numTestsPerEvictionRun}")
    private Integer numTestsPerEvictionRun;

    @Value("${redis.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;

    @Value("${redis.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${redis.testWhileIdle}")
    private boolean testWhileIdle;
}
4、根据要求,我们需要配置一个Redis连接池,直接在 RedisConfig 里注入一个Bean
	@Bean("jzRedisTemplate")
    @Primary
    public JedisPoolConfig jedisPoolConfig(){
        //创建连接池对象
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        //最大空闲数
        jedisPoolConfig.setMaxIdle(maxIdle);
        //连接池最大连接数数据库数量
        jedisPoolConfig.setMaxTotal(maxTotal);
        //连接最大等待时间
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        //逐出连接最小空空闲时间
        jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        //每次逐出的最大数量
        jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        //逐出扫描时间的间隔
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        //空闲时检查有效性
        jedisPoolConfig.setTestWhileIdle(testWhileIdle);
        return jedisPoolConfig;
    }
5、配置好了连接池,同样的,我们需要在 RedisConfig 里配置一个 Redis 工厂( 有点理解难度,所以解释了很多 )

先看配置的源码,再看为什么这么配哦!

JedisConnectionFactory并没有直接设置连接池的方法,所以我们需要通过 JedisPoolingClientConfigurationBuilder 去设置连接池,并且设置一些关于连接池的属性。

**解释一:**调用 JedisClientConfiguration.builder() 生成一个 JedisClientConfigurationBuilder 对象,我们可以在源码里查看到 JedisClientConfigurationBuilder 接口可以设置连接池

/**
		 * Enable connection-pooling.
		 * <p />
		 * Applies only to single node Redis. Sentinel and Cluster modes use always connection-pooling regardless of the
		 * pooling setting.
		 *
		 * @return {@link JedisPoolingClientConfigurationBuilder}.
		 */
		JedisPoolingClientConfigurationBuilder usePooling();

/**
		 * @param poolConfig must not be {@literal null}.
		 * @return {@literal this} builder.
		 * @throws IllegalArgumentException if poolConfig is {@literal null}.
		 */
		JedisPoolingClientConfigurationBuilder poolConfig(GenericObjectPoolConfig poolConfig);

配置好以后,我们还需要 创建工厂对象

//工厂对象
JedisConnectionFactory factory=new JedisConnectionFactory(redisStandaloneConfiguration,jedisClientConfiguration.build());

查看 JedisConnectionFactory 的构造方法,我们需要的是一个 JedisClientConfiguration 对象,而不是 JedisClientConfigurationBuilder对象,所以我们需要调用 JedisClientConfigurationBuilder 类提供的 build() 方法创造一个 JedisClientConfiguration 对象。

/**
	 * Constructs a new {@link JedisConnectionFactory} instance using the given {@link RedisStandaloneConfiguration} and
	 * {@link JedisClientConfiguration}.
	 *
	 * @param standaloneConfig must not be {@literal null}.
	 * @param clientConfig must not be {@literal null}.
	 * @since 2.0
	 */
	public JedisConnectionFactory(RedisStandaloneConfiguration standaloneConfig, JedisClientConfiguration clientConfig) {

		this(clientConfig);

		Assert.notNull(standaloneConfig, "RedisStandaloneConfiguration must not be null!");

		this.standaloneConfig = standaloneConfig;
	}
/**
		 * Build the {@link JedisClientConfiguration} with the configuration applied from this builder.
		 *
		 * @return a new {@link JedisClientConfiguration} object.
		 */
		JedisClientConfiguration build();

配置工厂类

@Bean("jedisConnectionFactory")
    @Primary
    public JedisConnectionFactory jedisConnectionFactory(@Qualifier("jedisPoolConfig") JedisPoolConfig jedisPoolConfig){
        //redis连接配置
        RedisStandaloneConfiguration redisStandaloneConfiguration=new RedisStandaloneConfiguration();
        //设置连接的ip
        redisStandaloneConfiguration.setHostName(host);
        //设置密码
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        //端口号
        redisStandaloneConfiguration.setPort(port);
        //连接的数据库
        redisStandaloneConfiguration.setDatabase(database);
        //JedisConnectionFactory配置jedisPoolConfig
        JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
        //客户端超时时间单位是毫秒
        jedisClientConfiguration.connectTimeout(Duration.ofMillis(timeout));
        //连接池
        jedisClientConfiguration.usePooling().poolConfig(jedisPoolConfig);
        //工厂对象
        JedisConnectionFactory factory=new JedisConnectionFactory(redisStandaloneConfiguration,jedisClientConfiguration.build());
        return factory;
    }
6、配置好了 Redis 工厂和连接池后,我们只需要配置自定义的 RedisTemplate 了
 @Bean("RedisTemplateTest")
 public RedisTemplate<String,Object> RedisTemplate(@Qualifier("jedisConnectionFactory") RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
        initRedisTemplate(redisTemplate,redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * @deprecated : 初始化RedisTemplate的配置,配置序列化and工厂
     * @param redisTemplate
     * @return
     */
    public void initRedisTemplate(RedisTemplate<String,Object> redisTemplate, RedisConnectionFactory factory){
        // json 序列化配置,序列化所有对象
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会抛出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // string 的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        //设置连接工厂
        redisTemplate.setConnectionFactory(factory);
    }

这样我们就已经配置好了 Redis 连接池和自定义 RedisTemplate 了,但是建议对 RedisTemplate 再进行一层封装,封装一个 RedisUtil 类

7、封装 RedisUtil 类
public class RedisUtil {
	
    private RedisTemplate<String,Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    //...一些封装的方法
}    

在 RedisConfig 里配置一个 Bean,这个便是我们要使用的 RedisTemplate ,这里做的是进一步封装

@Bean("RedisUtil")
@Primary
public RedisUtil redisUtil(@Qualifier("RedisTemplateTest") RedisTemplate<String,Object> redisTemplate){
        RedisUtil redisUtil=new RedisUtil();
        redisUtil.setRedisTemplate(redisTemplate);
        return redisUtil;
    }
8、使用,在test类里自动注解,然后就可以使用了
@Autowired
    private RedisUtil redisUtil;

    @Test
    void contextLoads() {
        System.out.println(redisUtil.set("name","future"));
        System.out.println(redisUtil.get("name"));
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐