在我们之前的有一节文中说了使用redisson组件的使用。Java分布式开发利器-Redisson,那以此为基础,我们使用redisson组件作为配置微服务的配置中心,使我们的微服务配置库变为redis。
全网很少使用redis mysql等等作为配置库的例子,大部分使用阿里巴巴的开源框架Nacos,我见过很小很小的项目,做了一个很大很大的框架,咱也不清楚这个项目是怎么弄的,小项目大框架,真的是为了显示自己的能力,还是给开发人员增加工作量呢。
按照我的理解:小就做小巧点,整的那么大,冗余复杂,俩个字:难受
废话不多说,我们来配置看看如何使用redis作为配置中心。
1. 理解Spring Cloud Config中的EnvironmentRepository
在Spring Cloud Config中,EnvironmentRepository 是一个接口,它提供了从配置服务中检索环境变量和配置信息的功能。这个接口是 Spring Cloud Config 组件的一部分,它使得应用程序能够从外部配置源(如Git仓库或文件系统)中读取配置,而无需将这些配置硬编码到应用程序中。
EnvironmentRepository 通常与 Spring Cloud Config Server 一起使用,后者负责提供配置服务的存储和接口。当应用程序启动时,它会连接到配置服务,并从配置服务中加载其所需的配置。
我们这里举一个简单的示例,展示如何在 Spring 应用程序中EnvironmentRepository:
import org.springframework.cloud.config.EnvironmentRepository;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class MyEnvironmentRepository implements EnvironmentRepository {
@Override
public Environment findOne(String application, String profile, String label) {
// 这里可以添加自定义逻辑来获取配置信息
return new Environment(application, profile); // 返回从配置服务中获取的配置信息
}
}
既然我们了解到EnvironmentRepository,那么我们就可以用这个接口的实现来实现获取redis中的配置信息了。
2. 完成config配置
目前不用心急,我们在创建了spring cloud config项目工程之后,我们需要在它的配置中,明确告诉config,我用的是redis。
还有配置就是连接redis配置,我们采用的redisson的实现,所以请查看Java分布式开发利器-Redisson即可实现。
spring.application.name=office-config-manager
server.port=10051
spring.profiles.active=redis
3. 完成实现
首先完成一个查询redis配置信息字段的实现类,实现类完全按照config中的 application,profile,label的字段进行获取。
// redission链接
@Resource
private RedissonClient redissonClient;
// 配置获取项前缀 如:redis内的配置为 myconfig:dev:dao,
// 那么“myconfig:”就是 prefix的字段
// dev就是 label的字段
// profile 就是 dao字段
@Value("${spring.cloud.redis.profile.prefix}")
private String prefix;
/**
* <b>功能描述:</b>获取配置信息<br>
* <b>修订记录:</b><br>
* @param application
* @param profile
* @param label
*/
@Override
public String getRedisPropertiesValue(String application, String profile, String label) {
RBucket<String> configMap = redissonClient.getBucket(prefix + label + ":" + profile);
return configMap != null && configMap.isExists() ? configMap.get() : null;
}
完成了获取配置的接口,我们完成EnvironmentRepository的实现类。
@Slf4j
public class RedissonEnvironmentRepository implements EnvironmentRepository, Ordered {
@Resource
private IRedissonService redissonService;
private static final String REF_CONF_KEY = "conf-ref";
@Override
public Environment findOne(String application, String profile, String label) {
if (StringUtils.isEmpty(application) || StringUtils.isEmpty(profile)) {
return null;
}
String modelValueJson = redissonService.getRedisPropertiesValue(application, profile, label);
if (modelValueJson != null) {
// 主配置获取
Environment environment = new Environment(application, StringUtils.commaDelimitedListToStringArray(profile), label, null, null);
Map<String, String> config = getProDataMap(modelValueJson);
environment.add(new PropertySource(label + "/" + application + "-" + profile, config));
//获取需关联的配置
if (config != null && !config.isEmpty() && config.containsKey(REF_CONF_KEY)) {
String ref = config.get(REF_CONF_KEY) == null ? "" : config.get(REF_CONF_KEY);
List<String> confRef = Splitter.on(",").splitToList(ref);
for (String profile_ : confRef) {
modelValueJson = redissonService.getRedisPropertiesValue(application, profile_, label);
if (modelValueJson != null && !modelValueJson.isEmpty()) {
Map<String, String> refConfig = getProDataMap(modelValueJson);
environment.add(new PropertySource(label + "/" + application + "-" + profile_, refConfig));
} else {
log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
log.info("[{}]配置未获取到,请检查", profile_);
log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
}
}
return environment;
}
return new Environment(application, profile);
}
@Override
public int getOrder() {
return 0;
}
/**
* <b>功能描述:</b>获取properties文件中的内容,并返回map<br>
* <b>修订记录:</b><br>
*
* @return
*/
public static Map<String, String> getProDataMap(String proStr) {
Map<String, String> map = new HashMap<>();
Properties pro = new Properties();
Reader reader = null;
try {
reader = new StringReader(proStr);
pro.load(reader);
} catch (UnsupportedEncodingException e) {
log.error("读取失败", e);
} catch (IOException e) {
log.error("读取失败", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
Set<Map.Entry<Object, Object>> entrySet = pro.entrySet();
for (Map.Entry<Object, Object> entry : entrySet) {
map.put((String) entry.getKey(), (String) entry.getValue());
}
return map;
}
}
4. 配置redis
如:redis key是config_center:prod:testdemo
spring.application.name=testdemo-server
server.port=15550
conf-ref=eureka-client,dao,spring-boot,redis,druid
上面的配置中conf-ref代码,我还要引入外部的配置,那么配置中还有config_center:prod:druid,config_center:prod:dao这些配置key。分类配置,清晰明了。如图:
5. 客户端配置
客户端我们需要获取到配置中心的配置信息。那我们只需要在配置中标明config的IP端口即可。
#Config配置服务
spring.cloud.config.profile=manager
spring.cloud.config.name=application
spring.cloud.config.label=prod
spring.config.import=optional:configserver:http://127.0.0.1:10051