赞
踩
pom引入snakeyaml依赖
- <dependency>
- <groupId>org.yaml</groupId>
- <artifactId>snakeyaml</artifactId>
- <version>2.0</version>
- </dependency>
上代码
- public class UpdateYmlConfigUtil {
-
- public static void updateYmlConfig(String config, Object value) {
- String src;
- String path = System.getProperty("user.dir");
- // 根据环境确定配置文件路径
- String system = System.getProperty("os.name");
- if(system.toLowerCase().startsWith("win")){
- src = path + "/src/main/resources/application.yml";
- } else {
- src = path + "/config/application.yml";
- }
- File file = new File(src);
- Yaml yaml = new Yaml();
- // 记录 yaml 文件的注释信息
- UpdateYmlConfigUtil.CommentHolder holder = UpdateYmlConfigUtil.buildCommentHolder(file);
- FileWriter fileWriter = null;
- //层级map变量
- Map<String, Object> springMap, dataSourceMap, resultMap;
- try {
- //读取yaml文件,默认返回根目录结构
- resultMap = yaml.load(new FileInputStream(file));
- String[] split = config.split("\\.");
- //get出第一个节点项
- dataSourceMap = (Map<String, Object>) resultMap.get(split[0]);
- for (int i = 1; i < split.length -1; i++) {
- //get出倒数第二个节点项
- dataSourceMap = (Map<String, Object>) dataSourceMap.get(split[i]);
- }
- //修改最后节点项配置的数据
- dataSourceMap.put(split[split.length -1], value);
- //字符输出
- fileWriter = new FileWriter(new File(src));
- //用yaml方法把map结构格式化为yaml文件结构
- fileWriter.write(yaml.dumpAsMap(resultMap));
- //刷新
- fileWriter.flush();
- //关闭流
- fileWriter.close();
- } catch (Exception e) {
- throw new RuntimeException("yml file config update fail:", e);
- }
- // 填充注释信息
- holder.fillComments(file);
- }
-
- private static final String END = "END###";
- private static final Pattern COMMENT_LINE = Pattern.compile("^\\s*#.*$");
- private static final Pattern BLANK_LINE = Pattern.compile("^\\s*$");
- /**
- * 带注释的有效行, 使用非贪婪模式匹配有效内容
- */
- private static final Pattern LINE_WITH_COMMENT = Pattern.compile("^(.*?)\\s+#.*$");
-
- @Data
- @AllArgsConstructor
- private static class Comment {
- private String lineNoComment;
- private String lineWithComment;
- // 存在相同行时的索引 (不同key下相同的行, 如 a:\n name: 1 和 b:\n name: 1 )
- private Integer indexInDuplicates;
- private boolean isEndLine() {
- return END.equals(lineNoComment);
- }
- }
-
- @SneakyThrows
- private static UpdateYmlConfigUtil.CommentHolder buildCommentHolder(File file) {
- List<UpdateYmlConfigUtil.Comment> comments = new ArrayList<>();
- Map<String, Integer> duplicatesLineIndex = new HashMap<>();
- UpdateYmlConfigUtil.CommentHolder holder = new UpdateYmlConfigUtil.CommentHolder(comments);
- List<String> lines = FileUtils.readLines(file, StandardCharsets.UTF_8.toString());
- // 末尾加个标志, 防止最后的注释丢失
- lines.add(END);
- StringBuilder lastLinesWithComment = new StringBuilder();
- for (String line : lines) {
- if (StringUtils.isBlank(line) || BLANK_LINE.matcher(line).find()) {
- lastLinesWithComment.append(line).append('\n');
- continue;
- }
- // 注释行/空行 都拼接起来
- if (COMMENT_LINE.matcher(line).find()) {
- lastLinesWithComment.append(line).append('\n');
- continue;
- }
- String lineNoComment = line;
-
- boolean lineWithComment = false;
- // 如果是带注释的行, 也拼接起来, 但是记录非注释的部分
- Matcher matcher = LINE_WITH_COMMENT.matcher(line);
- if (matcher.find()) {
- lineNoComment = matcher.group(1);
- lineWithComment = true;
- }
- // 去除后面的空格
- lineNoComment = lineNoComment.replace("\\s*$", "");
- // 记录下相同行的索引
- Integer idx = duplicatesLineIndex.merge(lineNoComment, 1, Integer::sum);
- // 存在注释内容, 记录
- if (lastLinesWithComment.length() > 0 || lineWithComment) {
- lastLinesWithComment.append(line);
- comments.add(new UpdateYmlConfigUtil.Comment(lineNoComment, lastLinesWithComment.toString(), idx));
- // 清空注释内容
- lastLinesWithComment = new StringBuilder();
- }
- }
- return holder;
- }
-
- @AllArgsConstructor
- public static class CommentHolder {
- private List<UpdateYmlConfigUtil.Comment> comments;
- /**
- * 通过正则表达式移除匹配的行 (防止被移除的行携带注释信息, 导致填充注释时无法正常匹配)
- */
- public void removeLine(String regex) {
- comments.removeIf(comment -> comment.getLineNoComment().matches(regex));
- }
-
- @SneakyThrows
- private void fillComments(File file) {
- if (comments == null || comments.isEmpty()) {
- return;
- }
- if (file == null || !file.exists()) {
- throw new IllegalArgumentException("file is not exist");
- }
- List<String> lines = FileUtils.readLines(file, StandardCharsets.UTF_8.toString());
- Map<String, Integer> duplicatesLineIndex = new HashMap<>();
- int comIdx = 0;
- StringBuilder res = new StringBuilder();
- for (String line : lines) {
- Integer idx = duplicatesLineIndex.merge(line, 1, Integer::sum);
- UpdateYmlConfigUtil.Comment comment = getOrDefault(comments, comIdx);
- if (comment != null &&
- Objects.equals(line, comment.lineNoComment)
- && Objects.equals(comment.indexInDuplicates, idx)) {
- res.append(comment.lineWithComment).append('\n');
- comIdx++;
- } else {
- res.append(line).append('\n');
- }
- }
- UpdateYmlConfigUtil.Comment last = comments.get(comments.size() - 1);
- if (last.isEndLine()) {
- res.append(last.lineWithComment, 0, last.lineWithComment.indexOf(END));
- }
- FileUtils.write(file, res.toString(), StandardCharsets.UTF_8.toString());
- }
- }
-
- private static <T> T getOrDefault(List<T> vals, int index) {
- if (vals == null || vals.isEmpty()) {
- return null;
- }
- if (index >= vals.size()) {
- return null;
- }
- return vals.get(index);
- }
-
- }
测试:
- public static void main(String[] args) {
- updateYmlConfig("a.b.c.d", "cd");
- }
修改前:
修改后:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。