jedis 读写分离_读写分离的java redis 接口

目的:为了spring上下文添加读写分离的接口,可以在启动后自动注入redis只读接口或可读写接口

1. 定义一个相关的functional interface - 在spring boot的启动类里面要用到(@EnableDynamicKeyValueServiceCreation)

@Retention(value = RetentionPolicy.RUNTIME)

@Import(KeyValueServiceRegister.class)

public @interface EnableDynamicKeyValueServiceCreation {

}

2. 定义只读接口和可读写接口

public interface KeyValueReadService { String get(String key); ...}

public interface KeyValueReadWriteService extends KeyValueReadService { void set(String key, String value); ..}

3. 实现类

public class RedisConfigInfo {

private String hostName;

private int port;

private String password;

private JedisPoolConfig poolConfig;

}

public abstract class AbstractRedisOperation {

private final JedisPool jedisPool;

public AbstractRedisOperation (RedisConfigInfo info) { jedisPool = ...;}

}

public class RedisReadServiceImpl extends AbstractRedisOperation implements KeyValueReadService {

public RedisReadServiceImpl(RedisConfigInfo temp) {

super(temp);

}

@Override

public String get(String key) {

return stringValueOps.get(key);

}

}

4. 通过spring去获取redis的配置信息

@Component

public class KeyValueServiceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

private static Logger logger = LoggerFactory.getLogger(KeyValueServiceRegister.class);

private Map beanDefinitionMap = null;

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,

BeanDefinitionRegistry registry) {

if (beanDefinitionMap == null || beanDefinitionMap.isEmpty()) {

logger.warn("beanDefinitions is empty");

return;

}

String beanName;

BeanDefinition beanDefinition;

for (Map.Entry entry : beanDefinitionMap.entrySet()) {

beanName = entry.getKey();

beanDefinition = entry.getValue();

registry.registerBeanDefinition(beanName, beanDefinition);

}

}

@SuppressWarnings("rawtypes")

@Override

public void setEnvironment(Environment environment) {

String prefix = environment.getProperty("prefix.keyvalue.cache", "kv.");

Properties props = new Properties();

MutablePropertySources propSrcs = ((AbstractEnvironment) environment).getPropertySources();

StreamSupport.stream(propSrcs.spliterator(), false)

.filter(ps -> ps instanceof EnumerablePropertySource)

.map(ps -> ((EnumerablePropertySource) ps).getPropertyNames())

.flatMap(Arrays::stream).filter(name -> name.startsWith(prefix)).forEach(

propName -> props.setProperty(propName, environment.getProperty(propName)));

beanDefinitionMap = Collections

.unmodifiableMap(KeyValueServiceHelper.buildBeanDefinitionMap(props));

}

}

5. 根据配置信息构建bean

public class KeyValueServiceHelper {

private static final String POSFIX_READ = ".r";

private static final String POSFIX_WRITE = ".w";

public static final Map buildDataSourceMap(Properties prop) {

if (prop == null || prop.isEmpty()) {

return Collections.emptyMap();

}

Map result = new HashMap<>();

Set keys = prop.stringPropertyNames();

Properties temp;

String dsName;

for (String key : keys) {

dsName = key;

if (!isKeyValueServiceBeanName(key)) {

dsName = removePosfix(key);

}

temp = result.get(dsName);

if (temp == null) {

temp = new Properties();

result.put(dsName, temp);

}

temp.setProperty(key, prop.getProperty(key));

}

return result;

}

public static final boolean isKeyValueServiceBeanName(String str) {

if (StringUtils.isBlank(str)) {

return false;

}

return str.endsWith(POSFIX_READ) || str.endsWith(POSFIX_WRITE);

}

public static final String removePosfix(String str) {

if (StringUtils.isBlank(str)) {

return str;

}

int idx = str.lastIndexOf(".");

if (idx == -1) {

return str;

}

return str.substring(0, idx);

}

public static final String resolveBeanClassName(final String beanName,

final String connectionStr) {

if (StringUtils.isBlank(beanName)) {

throw new IllegalArgumentException("bean name is blank");

}

if (StringUtils.isBlank(connectionStr)) {

throw new IllegalArgumentException("connectionStr is blank");

}

if (!RedisConnectionHelper.isRedisConnectionString(connectionStr)) {

throw new IllegalArgumentException("connectionStr is invalid");

}

if (beanName.endsWith(POSFIX_READ)) {

return RedisReadServiceImpl.class.getName();

}

if (beanName.endsWith(POSFIX_WRITE)) {

return RedisReadWriteServiceImpl.class.getName();

}

throw new IllegalArgumentException("beanName is invalid,should end with '.r' or '.w'");

}

public static final Map buildBeanDefinitionMap(Properties props) {

Map cacheSources = buildDataSourceMap(props);

if (cacheSources == null || cacheSources.isEmpty()) {

return Collections.emptyMap();

}

BeanDefinition def;

String beanName;

String connectionStr;

String beanClassName;

Properties prop;

RedisConfigInfo info;

Map beanMap =

new HashMap(cacheSources.size());

for (Map.Entry entry : cacheSources.entrySet()) {

beanName = entry.getKey();

prop = entry.getValue();

connectionStr = prop.getProperty(beanName);

if (!RedisConnectionHelper.isRedisConnectionString(connectionStr)) {

continue;

}

info = RedisConnectionHelper.parseRedisConfigInfo(prop, beanName);

def = new GenericBeanDefinition();

beanClassName = KeyValueServiceHelper.resolveBeanClassName(beanName, connectionStr);

def.setBeanClassName(beanClassName);

def.getConstructorArgumentValues().addGenericArgumentValue(info);

beanMap.put(beanName, def);

}

return beanMap;

}

}

6. 如何使用

a. 在SpringBoot的启动类里面加上@EnableDynamicKeyValueServiceCreation

b. 配置文件里面加上读写分离的redis的配置信息 - 读的是.r结尾,可写的是.w结尾

c. 在需要只读redis的service里面, 直接注入(@KeyValueReadService (name=**.r)

d. 在需要读写redis的service里面, 直接注入(@KeyValueReadService (name=**.w)

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页