如何在 spring boot 中为 redis 实现多租户
How to implement multitenancy for redis in spring boot
我正在努力使我的整个应用程序成为多租户,但卡在了 Redis 上。到目前为止,我创建了一个 JedisConnectionFactory 的映射并试图将它传递给 RedisTemplate 但它抛出 java.lang.IllegalArgumentException: template not initialized; call afterPropertiesSet() before using it.
以下是代码片段:
@Component
public class RedisConfiguration {
@Autowired
private DSConfig dsConfig;
private Map<String,JedisConnectionFactory> jedisConnectionFactoryMap = new HashMap<>();
private static Logger LOGGER = LoggerFactory.getLogger(RedisConfiguration.class);
@PostConstruct
public void initializeJedisConnectionFactories() {
for(DatasourceDetail datasourceDetail : dsConfig.getDatasources()) {
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
redisConfig.setHostName(datasourceDetail.getRedisHost());
redisConfig.setPassword(RedisPassword.of(datasourceDetail.getRedisPassword()));
redisConfig.setPort(Integer.parseInt(datasourceDetail.getRedisPort()));
JedisClientConfiguration configuration = JedisClientConfiguration.builder().usePooling().
poolConfig(new JedisPoolConfig()).build();
jedisConnectionFactoryMap.put(datasourceDetail.getTenantId()
,new JedisConnectionFactory(redisConfig,configuration));
}
LOGGER.info("Connection factory count " + jedisConnectionFactoryMap.size());
}
public RedisTemplate< String, Object > redisTemplate() throws Exception {
final RedisTemplate< String, Object > template = new RedisTemplate< String, Object >();
template.setConnectionFactory( jedisConnectionFactory() );
template.setKeySerializer( new StringRedisSerializer() );
template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
template.setValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
return template;
}
JedisConnectionFactory jedisConnectionFactory() throws Exception {
if(TenantContext.getCurrentTenant()==null) {
throw new Exception("No tenant context found");
}
LOGGER.info("Returning redis connection for tenant" + TenantContext.getCurrentTenant());
return jedisConnectionFactoryMap.get(TenantContext.getCurrentTenant());
}
}
我正在使用如下的redis模板:
@CrossOrigin("*")
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisConfiguration redisConfiguration;
@GetMapping("/set")
@ResponseBody
public Object set(@RequestParam(value = "key", required = true) String key,
@RequestParam(value = "value", required = true) String value) throws Exception {
redisConfiguration.redisTemplate().opsForValue().set( key,value );
return true;
}
@GetMapping("/get")
@ResponseBody
public Object get(@RequestParam(value = "key", required = true) String key) throws Exception {
redisConfiguration.redisTemplate().opsForValue().get(key);
return true;
}
}
无论如何我可以用更好的方式实现它或者 spring redis 提供的任何其他方式吗?
最后我能够通过显式调用 afterPropertiesSet() 来解决。
我正在努力使我的整个应用程序成为多租户,但卡在了 Redis 上。到目前为止,我创建了一个 JedisConnectionFactory 的映射并试图将它传递给 RedisTemplate 但它抛出 java.lang.IllegalArgumentException: template not initialized; call afterPropertiesSet() before using it.
以下是代码片段:
@Component
public class RedisConfiguration {
@Autowired
private DSConfig dsConfig;
private Map<String,JedisConnectionFactory> jedisConnectionFactoryMap = new HashMap<>();
private static Logger LOGGER = LoggerFactory.getLogger(RedisConfiguration.class);
@PostConstruct
public void initializeJedisConnectionFactories() {
for(DatasourceDetail datasourceDetail : dsConfig.getDatasources()) {
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
redisConfig.setHostName(datasourceDetail.getRedisHost());
redisConfig.setPassword(RedisPassword.of(datasourceDetail.getRedisPassword()));
redisConfig.setPort(Integer.parseInt(datasourceDetail.getRedisPort()));
JedisClientConfiguration configuration = JedisClientConfiguration.builder().usePooling().
poolConfig(new JedisPoolConfig()).build();
jedisConnectionFactoryMap.put(datasourceDetail.getTenantId()
,new JedisConnectionFactory(redisConfig,configuration));
}
LOGGER.info("Connection factory count " + jedisConnectionFactoryMap.size());
}
public RedisTemplate< String, Object > redisTemplate() throws Exception {
final RedisTemplate< String, Object > template = new RedisTemplate< String, Object >();
template.setConnectionFactory( jedisConnectionFactory() );
template.setKeySerializer( new StringRedisSerializer() );
template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
template.setValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
return template;
}
JedisConnectionFactory jedisConnectionFactory() throws Exception {
if(TenantContext.getCurrentTenant()==null) {
throw new Exception("No tenant context found");
}
LOGGER.info("Returning redis connection for tenant" + TenantContext.getCurrentTenant());
return jedisConnectionFactoryMap.get(TenantContext.getCurrentTenant());
}
}
我正在使用如下的redis模板:
@CrossOrigin("*")
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisConfiguration redisConfiguration;
@GetMapping("/set")
@ResponseBody
public Object set(@RequestParam(value = "key", required = true) String key,
@RequestParam(value = "value", required = true) String value) throws Exception {
redisConfiguration.redisTemplate().opsForValue().set( key,value );
return true;
}
@GetMapping("/get")
@ResponseBody
public Object get(@RequestParam(value = "key", required = true) String key) throws Exception {
redisConfiguration.redisTemplate().opsForValue().get(key);
return true;
}
}
无论如何我可以用更好的方式实现它或者 spring redis 提供的任何其他方式吗?
最后我能够通过显式调用 afterPropertiesSet() 来解决。