YAML 技术研究

YAML预研文档

YAML概要

YAML是”YAML Ain’t a Markup Language”(YAML不是一种置标语言)的递归缩写,早先YAML的意思其实是:”Yet Another Markup Language”(另外一种置标语言),但为了强调这种语言以数据做为中心,而不是以置标语言为重点,而用返璞词重新命名,YAML的官方定义很简单,即一种人性化的数据格式定义语言,其主要功能用途类似于XML或JSON,YAML使用空白字符和分行来分隔数据,且巧妙避开各种封闭符号,如:引号、括号等,以避免这些符号在复杂层次结构中变得难以辨认。YAML的语法与高阶语言类似,可以很简单地表述序列(java中的list)、杂凑表(java中的map)、标量(java中的基本类型等)数据结构,它重点强调可阅读性。

YAML vs XML

与YAML相似的数据格式定义语言是XML,YAML比XML优越性表现在

优势:

  • YAML的可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现

上面5条是XML不足的地方,同时,YAML也具有XML的下列优点:

  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

YAML类似于XML的数据描述语言,语法比XML简单很多,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。


YAML vs JSON

JSON的语法其实是YAML的子集,大部分的JSON文件都可以被YAML的剖析器剖析。虽然大部分的数据分层形式也可以使用类似JSON的格式,不过YAML并不建议这样使用,除非这样编写能让文件可读性增加,更重要的是,YAML的许多扩展在JSON是找不到的,如:进阶资料形态关系锚点字串不需要引号映射资料形态会储存键值的顺序等。

YAML用途

脚本语言

由于实现简单,解析成本很低,YAML特别适合在脚本语言中使用。列一下现有的语言实现:Ruby,Java,Perl,Python,PHP,OCaml,JavaScript,除了Java,其他都是脚本语言。

序列化

YAML比较适合做序列化。因为它是宿主语言数据类型直转的。

配置文件

YAML做配置文件也不错。写YAML要比写XML快得多(无需关注标签或引号),并且比ini文档功能更强。

调试

由于其很强的阅读性,用于调试过程中dump出信息供分析也是一种比较方便的做法。

YAML缺陷与不足

YAML没有自己的数据类型的定义,而是使用实现语言的数据类型。一个YAML文件,在不同语言中解析后得到的数据类型可能会不同,由于其兼容性问题,不同语言间的数据流转不建议使用YAML。

YAML语法与范例

  • YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16
  • 使用空白字符(不能使用Tab)分层,同层元素左侧对齐
  • 单行注解由井字号( # )开始,可以出现在行中任何位置
  • 每个清单成员以单行表示,并用短杠+空白(- )起始
  • 每个杂凑表的成员用冒号+空白(: )分开键和值
  • 杂凑表的键值可以用问号 (?)起始,表示多个词汇组成的键值
  • 字串一般不使用引号,但必要的时候可以用引号框住
  • 使用双引号表示字串时,可用倒斜线(\)进行特殊字符转义
  • 区块的字串用缩排和修饰词(非必要)来和其他资料分隔,有新行保留(使用符号|)或新行折叠(使用符号>)两种方式
  • 在单一档案中,可用连续三个连字号(---)区分多个档案
  • 可选择性的连续三个点号(...)用来表示档案结尾(在流式传输时非常有用,不需要关闭流即可知道到达结尾处)
  • 重复的内容可使从参考标记星号 (*)复制到锚点标记(&
  • 指定格式可以使用两个惊叹号 ( !! ),后面接上名称
receipt:     Oz-Ware Purchase Invoice
date:        2007-08-06
customer:
    given:   Dorothy
    family:  Gale
items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4
    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers 
      price:     100.27
      quantity:  1
bill-to:  &id001
    street: | 
            123 Tornado Alley
            Suite 16
    city:   East Westville
    state:  KS
ship-to:  *id001   
specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the 
    man behind the curtain.
...

这个文件的的顶层由七个键值组成:其中一个键值”items”,是个两个元素构成的清单,清单中的两个元素同时也是包含了四个键值的杂凑表。
文件中重复的部分处理方式:使用锚点(&)和参考(*)标签将”bill-to”杂凑表的内容复制到”ship-to”杂凑表。也可以在文件中加入选择性的空行,以增加可读性。

YAML的JAVA实现

YAML已经有了多种语言不少实现,详见YAML官网
一般YAML文件扩展名为.yaml,比如John.yaml,其内容为:

name: John Smith
age: 37
children:
    - name: Jimmy Smith
      age: 15
    - name: Jenny Smith
      age: 12
spouse:
    name: Jane Smith
    age: 25

由于yaml的超强可读性,我们了解到:John今年37岁,两个孩子Jimmy 和Jenny活泼可爱,妻子Jane年轻美貌,而且年仅25岁,一个幸福的四口之家。
对John.yaml进行java描述,抽象出一个Person类,如下:

public class Person {
    private String name;
    private int age;
    private Person sponse;
    private Person[] children;
    // setXXX, getXXX方法略.
}

现在我们使用java装配一个Jone:

    Person john = new Person();
    john.setAge(37);
    john.setName("John Smith");
    Person sponse = new Person();
    sponse.setName("Jane Smith");
    sponse.setAge(25);
    john.setSponse(sponse);
    Person[] children = {new Person(), new Person()};
    children[0].setName("Jimmy Smith");
    children[0].setAge(15);
    children[1].setName("Jenny Smith");
    children[1].setAge(12);
    john.setChildren(children);

使用SnakeYAML实现

项目主页:http://code.google.com/p/snakeyaml/
使用手册:https://code.google.com/p/snakeyaml/wiki/Documentation
SnakeYAML是一个标准的YAML的java实现,它有以下特点:

  • 完全支持YAML 1.1,可以跑通规范中的所有示例
  • 支持YAML的所有类型
  • 支持UTF-8/UTF-16的输入和输出
  • 提供了本地java对象的序列化和反序列化的高层API
  • 提供相对合理的错误提示信息

使用SnakeYAML将john dump出来,如果有引用相同对象,则dump出到yaml文件会自动使用&*进行锚点和引用

DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
//Yaml yaml = new Yaml();
String dump = yaml.dump(john);
System.out.println(dump);

内容如下:

!!Person
age: 37
children:
- age: 15
  children: null
  name: Jimmy Smith
  sponse: null
- age: 12
  children: null
  name: Jenny Smith
  sponse: null
name: John Smith
sponse:
  age: 25
  children: null
  name: Jane Smith
  sponse: null

现在用SnakeYAML把yaml load进来,如果yaml文件中使用了&*,则会自动对load出来的对象赋相同的值

Yaml yaml = new Yaml();
Object load = yaml.load(new FileInputStream(new File("jhon.yaml")));
System.out.println(load.getClass());
System.out.println(yaml.dump(load));

Yaml yaml = new Yaml(options);
Person person = yaml.loadAs(inputStream, Person.class);
System.out.println(person.getSponse().getChildren().length);

如果一个yaml文件中有多个文档,由---分割,解析如下:

Yaml yaml = new Yaml();
        int counter = 0;
        for (Object data : yaml.loadAll(input)) {
            System.out.println(data);
            counter++;
        }

保存一个Map对象:

Map<String, Object> data = new HashMap<String, Object>();
        data.put("name", "Silenthand Olleander");
        data.put("race", "Human");
        data.put("traits", new String[] { "ONE_HAND", "ONE_EYE" });
        Yaml yaml = new Yaml();
        String output = yaml.dump(data);
        System.out.println(output);
    // or
    StringWriter writer = new StringWriter();
    yaml.dump(data, writer);
    System.out.println(writer.toString());

将多个文档dump出到同一个yaml文件中去:

List<Integer> docs = new LinkedList<Integer>();
    for (int i = 1; i < 4; i++) {
        docs.add(i);
    }
    DumperOptions options = new DumperOptions();
    //options.setCanonical(true);
    options.explicitStart(true);
    Yaml yaml = new Yaml(options);
    System.out.println(yaml.dump(docs));
    System.out.println(yaml.dumpAll(docs.iterator()));
--- [1, 2, 3]

--- 1
--- 2
--- 3

YAML与java类型对照表:

YAMLJAVA
!nullnull
!!boolBoolean
!!intInteger, Long, BigInteger
!!floatDouble
!!binaryString
!!timestampjava.util.Date, java.sql.Date, java.sql.Timestamp
!!omap, !!pairsList of Object[]
!!setSet
!!strString
!!seqList
!!mapMap

集合的默认实现是:

  • List:  ArrayList
  • Map:  LinkedHashMap

使用JYaml实现

JYaml(最新版本是2007年的,可以考虑放弃了),使用JYaml把Jone “Dump” 出来:

    File dumpfile = new File("John_dump.yaml");
    Yaml.dump(john, dumpfile);

下面我们看看John_dump.yaml是什么样子:

--- !yaml.test.internal.Person
age: 37
children: !yaml.test.internal.Person[]
  - !yaml.test.internal.Person
    age: 15
    name: Jimmy Smith
  - !yaml.test.internal.Person
    age: 12
    name: Jenny Smith
name: John Smith
sponse: !yaml.test.internal.Person
  age: 25
  name: Jane Smith

其中!yaml.test.internal.Person是一些类型的信息。load的时候需要用。
现在用JYaml把Jone_dump.yaml load进来:

    Person john2 = (Person) Yaml.loadType(dumpfile, Person.class);

还可以用下面的代码dump出没有类型信息的John.yaml:

Yaml.dump(john,dumpfile, true);

我们再来看看JYaml对流处理的支持,为简便起见,我们只是把同一个john写10次:

    YamlEncoder enc = new YamlEncoder(new FileOutputStream(dumpfile));
    for(int i=0; i<10; i++){
        john.setAge(37+i);
        enc.writeObject(john);
        enc.flush();
    }
   enc.close();

下面再把这十个对象一个一个读出来(注意while循环退出的方式):

   YamlDecoder dec = new YamlDecoder(new FileInputStream(dumpfile));
   int age = 37;
   while(true){
       try{
           john = (Person) dec.readObject();
           assertEquals(age, john.getAge());
           age++;
       }catch(EOFException eofe){
           break;
       }
   }
<think>好的,用户想了解Spring Boot框架的技术细节和应用场景,需要相关的技术研究文档、教程和最佳实践。首先,我需要从提供的引用中提取有用的信息,结合自己的知识来组织回答。 根据引用[2],Spring Boot的主要优点包括自动配置、内嵌服务器、简化依赖管理等。技术细节部分可以围绕这些点展开,比如自动配置的原理,内嵌Tomcat或Jetty的实现方式,以及Starter依赖如何简化项目配置。引用[3]提到了Spring Boot 3.2.3的中文参考指南,可以推荐用户查阅官方文档,特别是自动配置和依赖管理的部分。引用[4]中的例子展示了如何使用Spring Boot集成Jsoup进行网络爬虫开发,这可以作为应用场景的实例。 应用场景方面,引用[1]提到Spring Boot在生产环境中的应用,比如微服务架构、快速构建单体应用等。需要强调Spring Boot在微服务中的角色,以及如何通过Spring Cloud进行扩展。此外,结合引用[4]的天眼查实战案例,可以说明Spring Boot在Web应用、数据访问和第三方集成中的实际应用。 最佳实践部分需要涵盖项目结构规范、配置管理、健康检查等,引用[2]和[3]提到了外部化配置和健康检查,可以详细说明如何利用Actuator进行监控。同时,引用[4]的依赖管理示例可以作为依赖管理的最佳实践案例。 还需要生成相关问题,确保覆盖用户可能关心的其他方面,比如与Spring MVC的区别、性能优化、微服务集成等。这些问题应基于回答中的内容,帮助用户进一步探索。 最后,检查回答是否符合系统级指令:行内公式是否正确,独立公式是否单独成段,中文回答,结构清晰,引用正确标注。确保没有使用Markdown格式,语言自然口语化。</think>### Spring Boot框架技术研究与应用详解 #### 一、核心技术细节 1. **自动配置原理** Spring Boot通过`@EnableAutoConfiguration`注解实现自动配置,其核心是`spring-boot-autoconfigure`模块中的条件化Bean加载。例如,当类路径中存在`DataSource`类时,自动配置数据源相关Bean[^2]。 2. **嵌入式容器** 默认集成Tomcat(也可切换为Jetty/Undertow),通过`spring-boot-starter-web`依赖实现。启动时通过`SpringApplication.run()`初始化内嵌服务器,无需外部部署WAR包[^2]。 3. **Starter依赖机制** 通过约定大于配置的思想,如`spring-boot-starter-data-jpa`包含JPA、Hibernate及相关数据库驱动,依赖关系自动解析。依赖声明示例: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ```[^3] #### 二、典型应用场景 1. **微服务架构** 作为微服务基础框架,配合Spring Cloud实现服务注册、配置中心等功能。生产环境中可通过`spring-boot-actuator`提供健康检查端点[^1]。 2. **快速构建Web应用** 支持RESTful API开发,集成Thymeleaf/FreeMarker模板引擎。例如通过`@RestController`注解声明API端点: ```java @RestController public class DemoController { @GetMapping("/hello") public String hello() { return "Hello Spring Boot!"; } } ``` 3. **数据访问集成** 自动配置JPA、MyBatis等ORM框架,通过`spring-boot-starter-data-jdbc`简化数据库操作。 4. **第三方服务集成** 如引用[4]所示案例,集成Jsoup实现网络爬虫: ```java @Service public class CrawlerService { public void crawlData(String url) { Document doc = Jsoup.connect(url).get(); // 数据解析逻辑 } } ``` #### 三、最佳实践建议 1. **项目结构规范** - 采用分层架构:controller/service/repository/domain - 配置文件放置于`src/main/resources`,区分`application-dev.yml`/`application-prod.yml` 2. **配置管理** ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/db username: root password: 123456 ``` 3. **健康检查与监控** 启用Actuator后访问`/actuator/health`获取应用状态,集成Prometheus实现指标监控[^1]。 4. **依赖管理技巧** 使用`dependencyManagement`统一管理版本号,避免依赖冲突: ```xml <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.2.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值