Spring Redis - Read configuration from application

2019-02-06 05:28发布

问题:

I have Spring Redis working using spring-data-redis with all default configuration likes localhost default port and so on.

Now I am trying to make the same configuration by configuring it in application.properties file. But I cannot figure out how should I create beans exactly that my property values are read.

Redis Configuration File

@EnableRedisHttpSession
@Configuration
public class SpringSessionRedisConfiguration {

@Bean
JedisConnectionFactory connectionFactory() {
    return new JedisConnectionFactory();
}

@Autowired
@Bean
RedisCacheManager redisCacheManager(final StringRedisTemplate stringRedisTemplate) {
    return new RedisCacheManager(stringRedisTemplate);
}

@Autowired
@Bean
StringRedisTemplate template(final RedisConnectionFactory connectionFactory) {
    return new StringRedisTemplate(connectionFactory);
}
}

Standard Parameters in application.properties

spring.redis.sentinel.master=themaster

spring.redis.sentinel.nodes=192.168.188.231:26379

spring.redis.password=12345

What I tried,

  1. I can possibly use @PropertySource and then inject @Value and get the values. But I don't want to do that as those properties are not defined by me but are from Spring.
  2. In this documentation Spring Redis Documentation, it only says that it can be configured using properties but doesn't show concrete example.
  3. I also went through Spring Data Redis API classes, and found that RedisProperties should help me, but still cannot figure out how exactly to tell Spring to read from properties file.

回答1:

You can use @PropertySource to read options from application.properties or other property file you want. Please look PropertySource usage example and working example of usage spring-redis-cache. Or look at this small sample:

@Configuration
@PropertySource("application.properties")
public class SpringSessionRedisConfiguration {

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

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

    @Bean
    public static PropertySourcesPlaceholderConfigurer    propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(redisHostName);
        factory.setPort(redisPort);
        factory.setUsePool(true);
        return factory;
    }

    @Bean
    RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        return redisTemplate;
    }

    @Bean
    RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate());
        return redisCacheManager;
    }
}

In present time (december 2015) the spring.redis.sentinel options in application.properties has limited support of RedisSentinelConfiguration:

Please note that currently only Jedis and lettuce Lettuce support Redis Sentinel.

You may read more about this in official documentation.



回答2:

Upon looking deeper I found this, could it be what you are looking for?

# REDIS (RedisProperties)
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.host=localhost # Redis server host.
spring.redis.password= # Login password of the redis server.
spring.redis.pool.max-active=8 # Max number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.pool.max-idle=8 # Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.pool.max-wait=-1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.port=6379 # Redis server port.
spring.redis.sentinel.master= # Name of Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of host:port pairs.
spring.redis.timeout=0 # Connection timeout in milliseconds. 

Refernce:https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html Searchterm Redis

From what I can see the values already exist and are defined as

spring.redis.host=localhost # Redis server host.
spring.redis.port=6379 # Redis server port.

if you want to create your own properties you can look at my previous post in this thread.



回答3:

I found this within the spring boot doc section 24 paragraph 7

@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {

    private String username;

    private InetAddress remoteAddress;

    // ... getters and setters

} 

Properties can then be modified via connection.property

Reference link: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties



回答4:

Here is an elegant solution to solve your issue :

@Configuration
@PropertySource(name="application", value="classpath:application.properties")
public class SpringSessionRedisConfiguration {

    @Resource
    ConfigurableEnvironment environment;

    @Bean
    public PropertiesPropertySource propertySource() {
        return (PropertiesPropertySource) environment.getPropertySources().get("application");
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        return new JedisConnectionFactory(sentinelConfiguration(), poolConfiguration());
    }

    @Bean
    public RedisSentinelConfiguration sentinelConfiguration() {
        return new RedisSentinelConfiguration(propertySource());
    }

    @Bean
    public JedisPoolConfig poolConfiguration() {
        JedisPoolConfiguration config = new JedisPoolConfiguration();
        // add your customized configuration if needed
        return config;
    }

    @Bean
    RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        return redisTemplate;
    }

    @Bean
    RedisCacheManager cacheManager() {
        return new RedisCacheManager(redisTemplate());
    }

}

so, to resume :

  • add a specific name for the @PropertySource
  • inject a ConfigurableEnvironment instead of Environment
  • get the PropertiesPropertySource in your ConfigurableEnvironment using the name you mentioned on your @PropertySource
  • Use this PropertySource object to construct your RedisSentinelConfiguration object
  • Don't forget to add 'spring.redis.sentinel.master' and 'spring.redis.sentinel.nodes' properties in you property file

Tested in my workspace, Regards



回答5:

I think this what you are looking for http://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html



回答6:

You can use the ResourcePropertySource to generate a PropertySource object.

PropertySource propertySource = new ResourcePropertySource("path/to/your/application.properties");

Then pass it to the constructor of the RedisSentinelConfiguration.



回答7:

Use @DirtiesContext(classMode = classmode.AFTER_CLASS) at each test class. This will surely work for you.



回答8:

This works for me :

@Configuration
@EnableRedisRepositories
public class RedisConfig {

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisProperties properties = redisProperties();
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(properties.getHost());
        configuration.setPort(properties.getPort());

        return new JedisConnectionFactory(configuration);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setValueSerializer(new GenericToStringSerializer<>(Object.class));
        return template;
    }

    @Bean
    @Primary
    public RedisProperties redisProperties() {
        return new RedisProperties();
    }

}

and properties file :

spring.redis.host=localhost
spring.redis.port=6379


回答9:

@Autowired
private JedisConnectionFactory connectionFactory;

@Bean
JedisConnectionFactory connectionFactory() {
    return connectionFactory
}