嗯...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中找到了解决方案
按上图所述,遇到这种报错需要在maven-shade-plugin中添加配置,如下图所示:
<transformer implementatinotallow="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()});}对应上述的代码,目录结构也要做相应的调整,如下图所示:
它会先获取configs下的bootstrap.yml文件,读取里面的server.active参数,通过参数内容找到对应目录下的文件地址,并通过fileSystem获取所有文件。