【Java】Vert.x打包后无法使用ConfigRetriever获取配置信息

嗯…Spring虽好但用多会厌。有没有性能更好的平替方案呢?有,Vert.x。于是重新出发学习Vert.x,学了之后发现其实还可以自己做一些封装,于是在Vert.x的基础上弄了一个名为vtx_fw的基础框架。不过框架尚未稳定暂时就不对外公开了,但是有些坑还是可以跟各位同好们分享一下的。

因此,我又挖坑了。开了一个Vert.x系列,希望通过自己填坑经验帮助到其他有需要的人。

首发第一篇讲的是ConfigRetriever无法获取配置信息。受Springboot影响vtx_fw项目结构也与springboot的类似,也是通过读取yaml文件获取配置信息,其中version1的Yaml配置获取将采用以下代码处理:

ConfigStoreOptions configStore = new ConfigStoreOptions();
configStore.setType(CONFIG_TYPE);
// 指定配置文件路径
JsonObject pathJson = new JsonObject();
pathJson.put(CONFIG_PARAM_PATH, CONFIG_DIRECTORY);
// 读取配置文件通配符
JsonArray patternArr = new JsonArray();
patternArr.add(new JsonObject().put(CONFIG_PARAM_PATTERNS, CONFIG_FORMAT_YAML + "/*.yaml")
    .put(CONFIG_PARAM_FORMAT, CONFIG_FORMAT_YAML));
pathJson.put(CONFIG_PARAM_FILESET, patternArr);
configStore.setConfig(pathJson);
// 配置获取所有yml文件数据
ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions().addStore(configStore));
// 获取配置信息
retriever.getConfig(conf -> {
    if (conf.succeeded()) {
        System.out.println("YamlConfig.start5:" + conf.result());
        YamlConstants.CONF_JSON = conf.result();
    } else {
        LOGGER.error("func[YamlConfig.start] Exception [{} - {}]",
            new Object[] {conf.cause(), conf.cause().getMessage()});
    }
});

在IDE工具中执行是没有问题的,能够正常获取某目录下的所有文件并可根据通配符“*”可以全部获取,如下所示:

{
	"databases": {
		"has-open": true,
		"db-type": "mysql",
		"nodes": [{
			"name": "test_write",
			"uri": "jdbc:mysql://127.0.0.1:3506/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8",
			"driver-class-name": "com.mysql.cj.jdbc.Driver",
			"username": "yzh",
			"password": "0624"
		}, {
			"name": "test_read",
			"uri": "jdbc:mysql://127.0.0.1:3506/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8",
			"driver-class-name": "com.mysql.cj.jdbc.Driver",
			"username": "yzh",
			"password": "0624"
		}],
		"hikari": {
			"pool-name": "vtx-hikari-pool",
			"minimum-idle": 100,
			"maximum-pool-size": 500,
			"idle-timeout": 18000
		},
		"retry": {
			"get-counter": 10,
			"interval": 500
		}
	},
	"zookeeper": {
		"zookeeper-hosts": "172.20.0.2:2181,172.20.0.3:2181,172.20.0.4:2181",
		"root-path": "io.kida.yuen",
		"retry": {
			"initial-sleep-time": 100,
			"max-times": 2
		},
		"has-open": false
	},
	"server": {
		"name": "vtx_biz",
		"active": "dev",
		"port": 8197,
		"context": "biz",
		"timeout": 120,
		"http": {
			"header": ["x-requested-with", "Access-Control-Allow-Origin", "origin", "Content-Type", "accept"]
		},
		"event-bus": {
			"timeout": 10000
		}
	},
	"thread": {
		"deploy": {
			"init": 1,
			"max-size": 128,
			"pool-name": "vtx-thread-pool"
		},
		"worker": 64,
		"init-pool-size": 32,
		"eventloop-pool-size": 64
	}
}

但是在打包成fat jar后目录路径发生变化获取数据为空,并因为YamlProcess没有包含在/META/service目录中,因此报以下错误:

2022-05-12 16:02:03,760:DEBUG main (BootstrapConfig.java:77) - In order to get the startup configuration first initialize the YamlConfig class...
log4j:WARN No appenders could be found for logger (io.vertx.core.logging.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2022-05-12 16:02:04,085:ERROR vert.x-eventloop-thread-1 (BootstrapConfig.java:107) - func[BootstrapConfig.setupAndDeploy] Main method error Exception [java.lang.IllegalArgumentException: Unknown configuration format `yaml`, supported types are [json, raw, properties] - java.lang.IllegalArgumentException: Unknown configuration format `yaml`, supported types are [json, raw, properties]]

通过在网上搜索,最终在StackOverflow中找到了解决方案

【Java】Vert.x打包后无法使用ConfigRetriever获取配置信息_第1张图片

按上图所述,遇到这种报错需要在maven-shade-plugin中添加配置,如下图所示:

<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>

加上配置后经验证还是未解决无法获取配置信息的问题。后来经过多次试验后得知“path”参数后面对应的应该是绝对路径,因此如果你的配置是外部配置,可以通过ConfigRetriever来获取。但如果需要读取fat jar中的配置文件,还是乖乖地用fileSystem来获取,如下图:

Buffer bootBfr = vertx.fileSystem().readFileBlocking(BOOTSTRAP_PATH);
try {
    Map<String, Object> reMap = new HashMap<>();

    if (null != bootBfr) {
        Map<?, ?> baseMap = (Map<?, ?>)new Yaml().load(bootBfr.toString());
        Map<String, Object> bootMap = baseMap.entrySet().stream()
            .collect(Collectors.toMap(entry -> String.valueOf(entry.getKey()), entry -> entry.getValue()));
        reMap.putAll(bootMap);

        String envStr = new JsonObject(bootMap).getJsonObject("server").getString("active");

        vertx.fileSystem().readDir(CONFIG_FOLDER + "/" + envStr, dirHeader -> {
            if (dirHeader.succeeded()) {
                List<String> fileList = dirHeader.result();
                if (null != fileList && !fileList.isEmpty()) {
                    for (String pathName : fileList) {
                        Buffer pluginBfr = vertx.fileSystem().readFileBlocking(pathName);
                        if (null != pluginBfr) {
                            Map<?, ?> pluginMap = (Map<?, ?>)new Yaml().load(pluginBfr.toString());
                            Map<String, Object> appMap = pluginMap.entrySet().stream().collect(Collectors
                                .toMap(entry -> String.valueOf(entry.getKey()), entry -> entry.getValue()));
                            reMap.putAll(appMap);
                        }
                    }
                }
            }
            YamlConstants.CONF_JSON = new JsonObject(reMap);
        });
    }
} catch (Exception e) {
    LOGGER.error("func[YamlConfig.start] Exception [{} - {}]", new Object[] {e.getCause(), e.getMessage()});
}

对应上述的代码,目录结构也要做相应的调整,如下图所示:

【Java】Vert.x打包后无法使用ConfigRetriever获取配置信息_第2张图片

它会先获取configs下的bootstrap.yml文件,读取里面的server.active参数,通过参数内容找到对应目录下的文件地址,并通过fileSystem获取所有文件。

你可能感兴趣的:(Java,java,spring,boot,vert.x)