通过Java修改consul配置(保留注释、保留缩进)

 

 

 

 

 

  直接上代码了,找了很久也没找到保留注释的三方包,snakeyaml 的缩进一直也有问题,就自己写了个正则方式的

  consul也没有相关接口,只接受整个的

  传key和value,替换相应value值,

  大佬有更好的方法希望能告诉我

<dependency>
    <groupId>com.orbitz.consul</groupId>
    <artifactId>consul-client</artifactId>
    <version>1.5.3</version>
</dependency>

  

 

 

String regex = buildRegexForKey(keyToFind);
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);
Matcher matcher = pattern.matcher(yamlContent);
if(matcher.find()){
    String content = matcher.group(0);
    String targetLine = this.getLine(keyToFind, content);
    if ("".equals(targetLine)) {
        // 按原值查询
        result = this.findByOriginal(
            yamlContent, keyToFind, newValue, result
        );
        replacement1 = result.getReplacement1();
        replacement2 = result.getReplacement2();
        addFlag = result.isAddFlag();
    } else {
        String[] parts = keyToFind.split("\\.");
        String param = parts[parts.length -1];
        Pair<String, String> pair = this.handleTargetLine(targetLine, param);
        // 获取到左右部分,可以赋值
        replacement1 = targetLine;
        replacement2 = pair.getKey() + " " + newValue;
    }

} else {
    // 按原值查询
    result = this.findByOriginal(
            yamlContent, keyToFind, newValue, result
    );
    replacement1 = result.getReplacement1();
    replacement2 = result.getReplacement2();
    addFlag = result.isAddFlag();
}

private String buildRegexForKey(String key) {

        String[] parts = key.split("\\.");
        StringBuilder regexBuilder = new StringBuilder();

        // 匹配每个部分的键和冒号,考虑到YAML的缩进
        for (int i = 0; i < parts.length; i++) {
            if (i == parts.length -1) { // 如果不是第一个部分,添加换行符和缩进
                regexBuilder.append("\\b").append(parts[i]).append(":\\s*");
            } else {
                regexBuilder.append("\\b").append(parts[i]).append(":\\s*\\n.*?");
            }
        }
//        regexBuilder.append("[^\\s]+"); // 匹配值直到下一个空白字符或换行符
        regexBuilder.append("([^\\n]*)"); // 匹配值直到下一个换行符

        return regexBuilder.toString();
    }
private String getLine(String key, String yamlContent) {
        String returnStr = "";
        String[] lines = yamlContent.split("\n");
        String[] keyParts = key.split("\\.");
        int length = keyParts.length;

        String lastKey = keyParts[length - 1];

        // 步骤1: 找到 'springlm.datasourcelm' 所在行的下面一行
        String parentKey;
        if (length >= 2) {
            parentKey = keyParts[length - 2];
        } else {
            parentKey = keyParts[length - 1];
        }


        String nextLine = null;
        int indentSpacesCount = 0;

        for (int i = 0; i < lines.length; i++) {
            String line = lines[i].trim();
            if (line.startsWith(parentKey + ":")) {
                // 确保下一行不是空行或注释
                String candidateLine = (i + 1 < lines.length) ? lines[i + 1] : "";
                if (!candidateLine.isEmpty() && !candidateLine.startsWith("#")) {
                    nextLine = candidateLine;
                    break;
                }
            }
        }

        // 如果没有找到 下一行,则返回null
        if (nextLine == null) {
            return returnStr;
        }

        // 步骤2: 获取下一行的空格数量
        indentSpacesCount = countLeadingSpaces(nextLine);

        // 步骤3: 构建用于匹配目标行的空格字符串
        String indentSpaces = buildSpaces(indentSpacesCount);

        // 步骤4: 根据空格数量和最后一个.后面的key,获取这个key的所在行
        for (String line : lines) {
            if (line.startsWith(indentSpaces + lastKey + ":")) {
                return line;
            }
        }

        return returnStr; // 如果没有找到匹配的行,返回null
    }

    // 辅助方法,用于计算字符串中前导空格的数量
    private int countLeadingSpaces(String line) {
        int count = 0;
        while (count < line.length() && line.charAt(count) == ' ') {
            count++;
        }
        return count;
    }

    // 辅助方法,用于构建由空格组成的字符串
    private String buildSpaces(int count) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }


    public Pair<String, String> handleTargetLine(String line, String key) {
        String regex = "(\\s*" + key + ":)\\s+(.+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(line);

        if (matcher.find()) {
            String prefix = matcher.group(1); // "urllm:" 及其前面的空格
            String url = matcher.group(2);     // URL 的其余部分
            return new Pair<>(prefix, url);
        } else {
            return null; // 或者抛出一个异常,取决于您的错误处理策略
        }
    }

    public UpdateResultDto findByOriginal(
            String yamlContent, String keyToFind,
            String newValue, UpdateResultDto result
    ) {
//        String pathRegex = "(\\b" + keyToFind + ")\\s*:\\s*([^\\n]+)";
        String pathRegex = "^(" + keyToFind + ")\\s*:\\s*([^\n]+)";
        Pattern pathPattern = Pattern.compile(pathRegex, Pattern.MULTILINE);
        Matcher pathMatcher = pathPattern.matcher(yamlContent);
        String replacement1 = null;
        String replacement2 = null;
        boolean addFlag = false;

        if (pathMatcher.find()) {
            replacement1 = pathMatcher.group(0); // 匹配到的整个键值对
            replacement2 = keyToFind + ": " + newValue; // 新的键值对
        } else {
            // 如果没有匹配到,说明是新增
            addFlag = true;
        }
        result.setReplacement1(replacement1);
        result.setReplacement2(replacement2);
        result.setAddFlag(addFlag);
        return result;
    }

  

 

posted on 2024-04-18 15:45  唯心、tt  阅读(120)  评论(0)    收藏  举报

导航