从零开始SpringCloud Alibaba实战(68)——Yml转properties文件

yml 文件的格式,转换为properties文件

IDEA 插件Convert YAML and Properties File

不足
(1)转化后,原 yml 配置文件消失(如果转出了问题,想看原配置文件,还看不了了);

(2)排序出现混乱,没有按照原 yml 文件数据进行输出(msg相关的配置本来在原yml文件中是第二个配置,转换后却成为了第一个;同理,mybatis的配置本是最后一个,转化后却放在了第二个);

(3)所有注释均不见了(所有相关的注释全都不见了,包括行级注释和末尾注释);

(4)某些值没有进行配置,但转化后,却显示为了 null 字符串(如 msg.sex 的配置);

(5)该插件仅IDEA有,Eclipse中还没有,不能垮开发工具使用;

工具类

package com.test.utils;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
 
/**
 * Yaml 配置文件转 Properties 配置文件工具类

 */
public class YmlUtils {
 
    /**
     * 将 yml 文件转化为 properties 文件
     *
     * @param ymlFileName 工程根目录下(非resources目录)的 yml 文件名称(如:abc.yml)
     * @return List<Node> 每个Nyml 文件中每行对应解析的数据
     */
    public static List<YmlNode> castProperties(String ymlFileName) {
        if (ymlFileName == null || ymlFileName.isEmpty() || !ymlFileName.endsWith(".yml")) {
            throw new RuntimeException("请输入yml文件名称!!");
        }
        File ymlFile = new File(ymlFileName);
        if (!ymlFile.exists()) {
            throw new RuntimeException("工程根目录下不存在 " + ymlFileName + "文件!!");
        }
        String fileName = ymlFileName.split(".yml", 2)[0];
        // 获取文件数据
        String yml = read(ymlFile);
        List<YmlNode> nodeList = getNodeList(yml);
        // 去掉多余数据,并打印
        String str = printNodeList(nodeList);
        // 将数据写入到 properties 文件中
        String propertiesName = fileName + ".properties";
        File file = new File(propertiesName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try (FileWriter writer = new FileWriter(file)) {
            writer.write(str);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return nodeList;
    }
 
    /**
     * 将yml转化为porperties文件,并获取转化后的键值对
     *
     * @param ymlFileName 工程根目录下的 yml 文件名称
     * @return 转化后的 porperties 文件键值对Map
     */
    public static Map<String, String> getPropertiesMap(String ymlFileName) {
        Map<String, String> map = new HashMap<>();
        List<YmlNode> list = castProperties(ymlFileName);
        for (YmlNode node : list) {
            if (node.getKey().length() > 0) {
                map.put(node.getKey(), node.getValue());
            }
        }
        return map;
    }
 
    private static String read(File file) {
        if (Objects.isNull(file) || !file.exists()) {
            return "";
        }
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] b = new byte[(int) file.length()];
            fis.read(b);
            return new String(b, StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
 
    private static String printNodeList(List<YmlNode> nodeList) {
        StringBuilder sb = new StringBuilder();
        for (YmlNode node : nodeList) {
            if (node.getLast().equals(Boolean.FALSE)) {
                continue;
            }
            if (node.getEmptyLine().equals(Boolean.TRUE)) {
                System.out.println();
                sb.append("\r\n");
                continue;
            }
            // 判断是否有行级注释
            if (node.getHeadRemark().length() > 0) {
                String s = "# " + node.getHeadRemark();
                System.out.println(s);
                sb.append(s).append("\r\n");
                continue;
            }
            // 判断是否有行末注释 (properties中注释不允许末尾注释,故而放在上面)
            if (node.getTailRemark().length() > 0) {
                String s = "# " + node.getTailRemark();
                System.out.println(s);
                sb.append(s).append("\r\n");
            }
            //
            String kv = node.getKey() + "=" + node.getValue();
            System.out.println(kv);
            sb.append(kv).append("\r\n");
        }
        return sb.toString();
    }
 
    private static List<YmlNode> getNodeList(String yml) {
        String[] lines = yml.split("\r\n");
        List<YmlNode> nodeList = new ArrayList<>();
        Map<Integer, String> keyMap = new HashMap<>();
        Set<String> keySet = new HashSet<>();
        for (String line : lines) {
            YmlNode node = getNode(line);
            if (node.getKey() != null && node.getKey().length() > 0) {
                int level = node.getLevel();
                if (level == 0) {
                    keyMap.clear();
                    keyMap.put(0, node.getKey());
                } else {
                    int parentLevel = level - 1;
                    String parentKey = keyMap.get(parentLevel);
                    String currentKey = parentKey + "." + node.getKey();
                    keyMap.put(level, currentKey);
                    node.setKey(currentKey);
                }
            }
            keySet.add(node.getKey() + ".");
            nodeList.add(node);
        }
        // 标识是否最后一级
        for (YmlNode each : nodeList) {
            each.setLast(getNodeLast(each.getKey(), keySet));
        }
        return nodeList;
    }
 
    private static boolean getNodeLast(String key, Set<String> keySet) {
        if (key.isEmpty()) {
            return true;
        }
        key = key + ".";
        int count = 0;
        for (String each : keySet) {
            if (each.startsWith(key)) {
                count++;
            }
        }
        return count == 1;
    }
 
    private static YmlNode getNode(String line) {
        YmlNode node = new YmlNode();
        // 初始化默认数据(防止NPE)
        node.setEffective(Boolean.FALSE);
        node.setEmptyLine(Boolean.FALSE);
        node.setHeadRemark("");
        node.setKey("");
        node.setValue("");
        node.setTailRemark("");
        node.setLast(Boolean.FALSE);
        node.setLevel(0);
        // 空行,不处理
        String trimStr = line.trim();
        if (trimStr.isEmpty()) {
            node.setEmptyLine(Boolean.TRUE);
            return node;
        }
        // 行注释,不处理
        if (trimStr.startsWith("#")) {
            node.setHeadRemark(trimStr.replaceFirst("#", "").trim());
            return node;
        }
        // 处理值
        String[] strs = line.split(":", 2);
        // 拆分后长度为0的,属于异常数据,不做处理
        if (strs.length == 0) {
            return node;
        }
        // 获取键
        node.setKey(strs[0].trim());
        // 获取值
        String value;
        if (strs.length == 2) {
            value = strs[1];
        } else {
            value = "";
        }
        // 获取行末备注
        String tailRemark = "";
        if (value.contains(" #")) {
            String[] vs = value.split("#", 2);
            if (vs.length == 2) {
                value = vs[0];
                tailRemark = vs[1];
            }
        }
        node.setTailRemark(tailRemark.trim());
        node.setValue(value.trim());
        // 获取当前层级
        int level = getNodeLevel(line);
        node.setLevel(level);
        node.setEffective(Boolean.TRUE);
        return node;
    }
 
    private static int getNodeLevel(String line) {
        if (line.trim().isEmpty()) {
            return 0;
        }
        char[] chars = line.toCharArray();
        int count = 0;
        for (char c : chars) {
            if (c != ' ') {
                break;
            }
            count++;
        }
        return count / 2;
    }
}
 
class YmlNode {
 
    /** 层级关系 */
    private Integer level;
    /** 键 */
    private String key;
    /** 值 */
    private String value;
    /** 是否为空行 */
    private Boolean emptyLine;
    /** 当前行是否为有效配置 */
    private Boolean effective;
    /** 头部注释(单行注释) */
    private String headRemark;
    /** 末尾注释 */
    private String tailRemark;
    /** 是否为最后一层配置 */
    private Boolean last;
 
    public Boolean getLast() {
        return last;
    }
 
    public void setLast(Boolean last) {
        this.last = last;
    }
 
    public Integer getLevel() {
        return level;
    }
 
    public void setLevel(Integer level) {
        this.level = level;
    }
 
    public String getKey() {
        return key;
    }
 
    public void setKey(String key) {
        this.key = key;
    }
 
    public String getValue() {
        return value;
    }
 
    public void setValue(String value) {
        this.value = value;
    }
 
    public Boolean getEmptyLine() {
        return emptyLine;
    }
 
    public void setEmptyLine(Boolean emptyLine) {
        this.emptyLine = emptyLine;
    }
 
    public Boolean getEffective() {
        return effective;
    }
 
    public void setEffective(Boolean effective) {
        this.effective = effective;
    }
 
    public String getHeadRemark() {
        return headRemark;
    }
 
    public void setHeadRemark(String headRemark) {
        this.headRemark = headRemark;
    }
 
    public String getTailRemark() {
        return tailRemark;
    }
 
    public void setTailRemark(String tailRemark) {
        this.tailRemark = tailRemark;
    }
 
}

测试的方法很简单,只需要将 yml 配置文件放在根目录下,然后写个 Test 类,调用里面的 castProperties 方法即可。

YmlUtils.castProperties(“application-dev.yml”);

互转

引入依赖

<dependency>
       <groupId>com.fasterxml.jackson.dataformat</groupId>
       <artifactId>jackson-dataformat-yaml</artifactId>
       <version>2.9.4</version>
</dependency>

<dependency>
       <groupId>com.fasterxml.jackson.dataformat</groupId>
       <artifactId>jackson-dataformat-properties</artifactId>
       <version>2.9.4</version>
</dependency>

工具类

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.dataformat.javaprop.JavaPropsFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLParser;

import java.io.*;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;

/**
 * @program: config
 * @description: 转换工具类

 **/
public class TransferUtils {

    private static final String ENCODING = "utf-8";

    public static void yml2Properties(String path) {
        final String DOT = ".";
        List<String> lines = new LinkedList<>();
        try {
            YAMLFactory yamlFactory = new YAMLFactory();
            YAMLParser parser = yamlFactory.createParser(
                    new InputStreamReader(new FileInputStream(path), Charset.forName(ENCODING)));

            String key = "";
            String value = null;
            JsonToken token = parser.nextToken();
            while (token != null) {
                if (JsonToken.START_OBJECT.equals(token)) {
                    // do nothing
                } else if (JsonToken.FIELD_NAME.equals(token)) {
                    if (key.length() > 0) {
                        key = key + DOT;
                    }
                    key = key + parser.getCurrentName();

                    token = parser.nextToken();
                    if (JsonToken.START_OBJECT.equals(token)) {
                        continue;
                    }
                    value = parser.getText();
                    lines.add(key + "=" + value);

                    int dotOffset = key.lastIndexOf(DOT);
                    if (dotOffset > 0) {
                        key = key.substring(0, dotOffset);
                    }
                    value = null;
                } else if (JsonToken.END_OBJECT.equals(token)) {
                    int dotOffset = key.lastIndexOf(DOT);
                    if (dotOffset > 0) {
                        key = key.substring(0, dotOffset);
                    } else {
                        key = "";
                        lines.add("");
                    }
                }
                token = parser.nextToken();
            }
            parser.close();

            System.out.println(lines);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void properties2Yaml(String path) {
        JsonParser parser = null;
        JavaPropsFactory factory = new JavaPropsFactory();
        try {
            parser = factory.createParser(
                    new InputStreamReader(new FileInputStream(path), Charset.forName(ENCODING)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            YAMLFactory yamlFactory = new YAMLFactory();
            YAMLGenerator generator = yamlFactory.createGenerator(
                    new OutputStreamWriter(new FileOutputStream(path), Charset.forName(ENCODING)));

            JsonToken token = parser.nextToken();

            while (token != null) {
                if (JsonToken.START_OBJECT.equals(token)) {
                    generator.writeStartObject();
                } else if (JsonToken.FIELD_NAME.equals(token)) {
                    generator.writeFieldName(parser.getCurrentName());
                } else if (JsonToken.VALUE_STRING.equals(token)) {
                    generator.writeString(parser.getText());
                } else if (JsonToken.END_OBJECT.equals(token)) {
                    generator.writeEndObject();
                }
                token = parser.nextToken();
            }
            parser.close();
            generator.flush();
            generator.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
从零开始一个 Spring Cloud 项目可以按照以下步骤进行: 1. 确保你的开发环境已经搭建好,包括 JDK、IDE(如 IntelliJ IDEA 或 Eclipse)和 Maven。 2. 创建一个新的 Maven 项目。在 IDE 中选择创建 Maven 项目,并选择合适的 Maven 模板。 3. 添加 Spring Boot 和 Spring Cloud 的依赖。在项目的 pom.xml 文件中添加以下依赖: ```xml <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Cloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> ``` 这里只是添加了 Spring Boot Web 和 Eureka Server 的依赖,你可以根据实际需求添加其他需要的依赖。 4. 创建一个 Eureka Server。在项目中创建一个启动类,并使用 `@EnableEurekaServer` 注解来启用 Eureka Server 功能。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } ``` 5. 配置 Eureka Server。在项目的 application.properties 或 application.yml 文件中添加以下配置: ```yaml server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false ``` 这里配置了 Eureka Server 的端口和禁止它自己注册到 Eureka Server 上。 6. 运行 Eureka Server。运行启动类的 `main` 方法来启动 Eureka Server。 7. 创建其他微服务。按照类似的步骤,创建其他的微服务,并在它们的配置中将它们注册到 Eureka Server 上,以实现服务的发现和调用。 以上只是一个简单的示例,你可以根据实际需求和项目架构进行更复杂的配置和开发。希望这些步骤对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值