前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Y服务-你真的懂 Yaml 吗?

Y服务-你真的懂 Yaml 吗?

作者头像
美码师
发布于 2019-07-30 07:35:07
发布于 2019-07-30 07:35:07
83700
代码可运行
举报
文章被收录于专栏:美码师美码师
运行总次数:0
代码可运行

Java 的世界里,配置的事情都交给了 Properties,要追溯起来这个模块还是从古老的JDK1.0 就开始了的。

"天哪,这可是20年前的东西了,我居然还在用 Properties.."

然而,本文的主角并不是Properties,而是Yaml。

这是新时代里微服务架构上的宠儿,和 Properties 相比起来,Yaml 显得有些弄潮儿。以往的大多数项目里,我们都可以发现 Properties配置文件的踪迹,这包括用作 业务属性配置的、机机接口交互的、国际化的等等用途。而少量的一些情况下,也存在一些"混合式"的做法,比如:

  • 使用 Xml 来表示一些模板
  • 使用一个 Json 格式化的字符串
  • 裸奔的文本格式,应用自解析 ...

混杂的配置方式往往出现在一些充满"坏味道"的项目里头,因为代码陈旧、斯人已矣 等原因,很难形成统一的方式。然而,除开 Properties 属性文件这种简单的配置方式之外,采用其他的方法不外乎都是为了适应配置复杂、多元化的诉求。

那么,Yaml 就是应对这种场景而产生的,在 SpringBoot 的官方文档中,有不少篇幅是 使用了 Yaml 语法的配置格式。下面介绍一下 Yaml 以及它是如何使用的。

一、什么是 Yaml

来自百科的定义:

"Yaml 是一个可读性高,易用的数据序列化格式,由 Clark Evans 在2001年首次发表。"

可见 Yaml 并不是一个很新的东西,只是在以前接触的人不多罢了。此外,Yaml也被各种编程语言及框架所支持, 通用性很高。 在Java体系中,一般的微服务框架都支持甚至优先推荐使用 Yaml 作为首选的配置语言。

而 Yaml 本身具有什么特点? 看看下面的一个实例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
environments:
    dev:
        url: https://dev.example.com
  name: Developer Setup
    prod:
        url: https://another.example.com
        name: My Cool App

这段语法等价的 Properties 为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

可见, yaml 相对来说更加的结构化,更适合用来表达一个对象。它在语法上有这样的特点:

  • 大小写敏感
  • 使用空格缩进表示层级关系,摒弃使用Tab键,这主要是考虑到不同平台上文本展现时需要对齐
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 使用 # 开头作为注释行
  • 使用 连接符(-)开头来描述数组元素

对比 Properties

Properties 可以很好的实现 Key-Value 的配置,包括作为一些国际化内容的配置方式。但 Properties 很难表现多层级的嵌套关系,此时如果用 Yaml 可以较好的弥补该短板。

对比 Json

Yaml 与 Json本身没有太多的优劣之分,两者都是结构化的表达式语言,但是Json的设计重点在于 简单易用、方便传输 的特性;而 Yaml 则侧重于可读性(更加在乎外观),几乎可以把 Yaml 看做是 Json 的一个"超集",即可读性更高(更漂亮) 的结构化格式。

此外,Json更加便于生成和解析,适合在各种跨语言、分布式的环境中传输和交互;与此同时, Yaml 则一般只是用作的配置较多。

关于 Yaml 的定义可以访问下面的地址:

http://www.yaml.org/spec/1.2/spec.html

二、Yaml 的语法

Yaml 是非常精简的, 它所定义的元素只有三个:

  • 对象:就是键值对的集合,对应于Java 中的 HashMap
  • 数组:指一组按序排列的值,对应于Java 中的 List
  • 单值:单个的、不可再分的值,比如 3,"Jackson"

对象如何表示

一个对象的属性、嵌套关系通过空格缩进对齐来表示,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
article:
    title: 一个人的自白书
    author:
        name: 陈玲
        gender: female

数组如何表示

数组的元素通过连接符(-)来表示,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
article:
    title: 一个人的自白书
    tags:
        - 传记
        - 社会
        - 人物

构成对象、数组内容的基本单元是单值,Yaml支持的单个值的类型有七种,如下:

类型

范例

字符串

Bob

布尔值

true

整数

199

浮点数

19.91

Null

~

时间

2001-12-14T22:14:09.10+08:00

日期

2019-01-09

其中,日期、时间使用的是 ISO 8601 国际标准格式,关于它的定义可以参考:https://www.w3.org/TR/NOTE-datetime

一般情况下单个值会在一行内结束。但如果遇到多行的字符串,可以使用一些特殊字符表示, 比如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
text: |
  Hello
  World

对应的结果为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ text: 'Hello\nWorld\n' }

可以用+表示保留字符串末尾的换行,-表示删除字符串末尾的换行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
text1: |+
  Hello


text2: |-
  Hello

对应的结果为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ text1: 'Hello\n\n\n', text2: 'Hello' }

除此之外,Yaml 还可以支持引用、函数、正则表达式等高级用法,但项目上一般很少用到。

三、操作 Yaml

目前用来操作 Yaml 的常用组件是 Snake Yaml,这个库支持标准的 Yaml 1.1 版本

SpringBoot 官方文档也介绍了整合该框架的方式,参考下面的地址:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-loading-yaml

下面提供 将SnakeYaml 整合到项目的样例。

A. 引入框架

在Maven的pom.xml文件中添加:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.21</version>
</dependency>

B. 代码片段

实现加载配置文件

如下面的代码,实现了从类路径config.yml文件中加载 yaml 配置内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
InputStream inputStream = YamlUtil.class.getClassLoader()
        .getResourceAsStream("config.yml");

Yaml yaml = new Yaml();
Map<String, Object> objectMap = yaml.load(inputStream);
System.out.println(objectMap.get("path"));

实现对象转换

定义如下的Pojo 对象:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class A{
    private String name = "hello";
    private List<B> bs = new ArrayList<B>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<B> getBs() {
        return bs;
    }

    public void setBs(List<B> bs) {
        this.bs = bs;
    }
}

public static class B{
    private String id = UUID.randomUUID().toString();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

通过 SnakeYaml 将对象输出为 Yaml 格式的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A a = new A();
a.getBs().add(new B());
a.getBs().add(new B());

Yaml yaml = new Yaml();
String aString = yaml.dumpAsMap(a);
System.out.println(aString);

输出结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bs:
- id: b3688f05-ea7e-436b-bc9a-9c5df555c7fd
- id: 7906224d-8ecc-43b8-bc3b-07985bc18ebd
name: hello

此时如果希望将Yaml 文本反过来转换为 A 对象,可以执行下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A a1 = new Yaml().parseToObject(aString, A.class);
...

C. 完整案例

最终,我们可以将 Yaml 文档的操作封装为一个工具类,方便在业务代码中集成。

YamlUtil.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class YamlUtil {

    /**
     * 从资源文件加载内容,并解析为Map对象
     *
     * @param path
     * @return
     */
    public static Map<String, Object> loadToMap(String path) {
        if (StringUtils.isEmpty(path)) {
            return Collections.emptyMap();
        }

        InputStream inputStream = YamlUtil.class.getClassLoader()
                .getResourceAsStream(path);

        Yaml yaml = new Yaml();
        Map<String, Object> objectMap = yaml.load(inputStream);
        return objectMap;
    }

    /**
     * 将字符串解析为Map对象
     *
     * @param content
     * @return
     */
    public static Map<String, Object> parseToMap(String content) {
        if (StringUtils.isEmpty(content)) {
            return Collections.emptyMap();
        }

        Yaml yaml = new Yaml();
        Map<String, Object> objectMap = yaml.load(content);
        return objectMap;
    }

    /**
     * 将字符串解析为类对象
     *
     * @param content
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T parseToObject(String content, Class<T> clazz) {
        if (StringUtils.isEmpty(content) || clazz == null) {
            return null;
        }

        Yaml yaml = new Yaml(new Constructor(clazz));
        T object = yaml.load(content);
        return object;
    }

    /**
     * 格式化对象
     *
     * @param object
     * @return
     */
    public static String format(Object object) {
        Yaml yaml = new Yaml();
        return yaml.dumpAsMap(object);
    }

}

至此,我们已经完成了 Yaml 的读写。当然,除了上述的 Snake Yaml 之外,还可以使用 流行的 Jackson 组件来完成类似功能,这里不再过多赘述,有兴趣的朋友可以自行尝试。

参考文档

阮一峰-YAML语言教程:

http://www.ruanyifeng.com/blog/2016/07/yaml.html

SnakeYaml 官方文档:

https://bitbucket.org/asomov/snakeyaml/wiki/Documentation

Yaml 1.2 规范:

http://www.yaml.org/spec/1.2/spec.html

SpringBoot-LoadingYaml

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-loading-yaml

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 美码师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
JDK1.8下载、安装和环境配置教程
链接:https://pan.baidu.com/s/1ozCGy53AIeQIHWL6s9oAbw 提取码:04lf
全栈程序员站长
2022/07/01
4K0
JDK1.8下载、安装和环境配置教程
Java基础之环境搭建
Java开发,搭建环境是第一步,今天就给大家分享一篇非常详细的Java环境搭建教程。
南风
2019/04/22
6730
Java基础之环境搭建
JAVA之 JDK安装及环境变量配置
Path=%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
shirayner
2018/08/10
5930
JAVA之 JDK安装及环境变量配置
java虚拟机(JVM)
虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
兮动人
2021/06/11
4800
java虚拟机(JVM)
Java基础篇——环境配置
今天就让阿Q带你一起完成一下java开发的环境配置。阿Q的系统是x64位的windows7,那么接下来阿Q就以该系统为基础进行讲解。如果大家有windows10或者是其他系统的话,有什么不懂的问题也可以联系阿Q,阿Q会尽力帮你解答的。
阿Q说代码
2021/05/13
3680
Java基础篇——环境配置
Java之安装JDK
首先需要下载 java 开发工具包 JDK,下载地址:https://www.oracle.com/java/technologies/downloads/
李小白是一只喵
2022/03/21
4710
Java之安装JDK
Java环境搭建
安装完成后,无需配置环境变量,直接在命令行敲 java -version ,可以看到出现如下提示信息:
小博测试成长之路
2021/03/06
1K0
Eclipse+Tomcat+MAVEN+SVN项目完整环境搭建
6.SVN安装   参考之前写的博客地址:http://www.cnblogs.com/zyw-205520/p/4598091.html 到此Eclipse+Tomcat+MAVEN+SVN项目完整环境搭建完成  如果疑问欢迎评论
一朵灼灼华
2022/08/05
3100
搭建Java环境JDK,和运行环境JRE
摘要总结:本文主要讲解了如何搭建Java环境JDK,和运行环境JRE,以及环境变量配置和验证。
别先生
2017/12/29
2.4K0
搭建Java环境JDK,和运行环境JRE
jmeter安装及使用基本教程「建议收藏」
附: JRE(Java Runtime Environment ) Java运行环境,用来运行JAVA程序的。 JDK(Java Development Kit) Java开发工具包,包含JRE。因此只需要下载安装JDK即可中。 JDK是Sun Microsystems针对Java开发员的产品,JSP运行环境需要JDK的支持。 JDK 是整个Java的核心,包括了Java运行环境,Java工具和Java基础的类库。
全栈程序员站长
2022/08/30
10.9K0
jmeter安装及使用基本教程「建议收藏」
Android开发环境的搭建
前言: 作为一个Android开发的新手,光开发环境就差点搭建了一天,最后发现自己走了很多弯路,在此写出希望能够帮助想入门的朋友。先说一下,开发Android app需要使用java语言,使用java需要安装JDK,并进行环境变量的配置,以前进行开发的时候往往需要分别安装JDK、SDK、ADT、eclipse,然后再通过一系列的操作将它们关联起来,直接在网上搜很多都是这种安装配置的教程,所以一开始我也是走的这种路线,费了半天事终于配置的差不多了,却发现SDK下载包的速度实在是慢的不得了,而且还经常安装不上。
用户1215536
2018/02/05
9390
Android开发环境的搭建
JAVA环境配置
http://www.oracle.com/technetwork/java/javase/downloads/index.html,点击如下下载按钮:
全栈程序员站长
2022/09/07
1.2K0
JAVA环境配置
[Java学习第二章]搭建Java环境
要编译和执行Java程序JDK是必备的,JDK全称是Java Developers Kits。
爱游博客
2019/08/06
9010
[Java学习第二章]搭建Java环境
Java环境变量配置
首先我们先对涉及到的两个比较重要的概念做一下解释,相信会对你排查错误有所帮助,毕竟:稳着来,我们能赢。
一头小山猪
2020/04/10
9.5K0
java运行环境配置(jdk配置) Java 博客 2 年前 桃李Taoli
oracle下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
taoli
2022/09/30
4660
java运行环境配置(jdk配置)
        
                    Java
                    博客 2 年前      桃李Taoli
Win10配置Java开发环境
软件开发环境,是一个程序的运行的支撑,Java作为近年来最热门的编程语言之一,越来越多的新人程序员选择Java来学习,它的开发环境搭建也是学习和使用这一编程语言的基础。今天我们将在Windows上配置Java的开发环境。
王荣胜
2020/03/13
2.4K0
Win10配置Java开发环境
java教程安装_java 安装教程
1) 新建变量名:JAVA_HOME,变量值:C:\Program Files\Java\jdk1.8.0_11
全栈程序员站长
2022/09/08
5.6K0
Java基础-Java语言开发环境搭建
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
cwl_java
2019/11/27
1K0
Win11下Java环境安装指南
推荐一个网站给想要了解或者学习人工智能知识的读者,这个网站里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏网站,请点击下方链接查看。 https://www.captainbed.cn/f1
鲜于言悠
2024/05/24
1K0
Win11下Java环境安装指南
Java-安装
JDK(Java Development Kit)是Java语言的软件开发工具包,主要用于移动设备、嵌入式设备上的Java应用程序。JDK是整个Java开发的核心,它包含了Java的运行环境,Java工具和Java基础的类库。
wangmcn
2022/07/25
8440
Java-安装
相关推荐
JDK1.8下载、安装和环境配置教程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档