文章目录

  • 参考资料
  • 运行环境
  • 1. SpringBoot概述
  • 1.1 Spring 缺点
  • 1.2 SpringBoot功能
  • 1.3 小结
  • 2. SpringBoot 快速入门
  • 2.1 使用案例
  • 2.2 实现步骤
  • 2.3 使用 IDEA2021 快速创建SpringBoot项目
  • 2.3 小结
  • 3. SpringBoot 起步依赖原理分析
  • 4. SpringBoot配置
  • 4.1 配置文件分类
  • 4.2 yaml
  • 基本语法
  • YAML : 数据格式
  • YAML: 参数引用
  • YAML: 小结
  • 4.3 读取配置文件内容
  • 4.3.1 @Value
  • 4.3.2 Environment
  • 4.3.3 @ConfigurationProperties
  • 4.4 profile
  • 4.4.1 多profile文件配置
  • 4.4.2 yml多文档方式
  • 4.4.3 通过JVM虚拟机配置激活yml文档
  • 4.4.4 通过progarming参数激活yml文档
  • 4.4.5 通过命令行在执行jar包时激活yml文档
  • 4.4.6 总结
  • 4.5 内部配置加载顺序
  • 4.6 外部配置加载顺序
  • 5. 总结


参考资料


运行环境


  • IDEA
  • JDK8
  • SpringBoot 2.6.2

1. SpringBoot概述


1.1 Spring 缺点

  • 配置繁琐
    spring2.5 基于注解的组件扫描, 消除了大量针对应用程序自身组件显示的XML配置
    spring3.0 引入了基于Java的配置、类型安全的可重构配置方式,可代替XML
  • 依赖繁琐
    在环境搭建时,需分析要导入哪些库的坐标,而且还要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。

1.2 SpringBoot功能

  • 自动配置
    Spring Boot的自动配置是一个运行时(即应用程序启动时)的过程,考虑了众多因素才决定Spring配置应该用哪个,不该用哪个,该过程是SpringBoot自动完成的。
  • 起步依赖
    本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,整合后可支持某项功能。
    简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
  • 辅助功能
    提供了一些大型项目中常见的非功能性特性,如嵌入式服务器,安全、指标、健康检测、外部配置等。

Spring Boot 并不是对 Spring功能上的增强, 而是提供了一种 快速使用 Spring的方式。

1.3 小结

SpringBoot提供了一种快速开发Spring项目的方式,并非是对Spring功能上的增强。

Spring的缺点:

  • 配置繁琐
  • 依赖繁琐

2. SpringBoot 快速入门


2.1 使用案例

需求: 搭建SpringBoot工程,定义helloController.hello()方法,返回 “Hello SpringBoot!”

注意:@SpringBootApplication标记的类必须在其他所有类的外层,否则启动会报错

springboot 子模块依赖父级本地包 springbootapplication依赖_spring boot

2.2 实现步骤

  • 创建Maven项目
  • 导入SpringBoot起步依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Demo01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <!-- SpringBoot工程需要继承的父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
    </parent>

    <dependencies>
        <!-- web 开发的起步依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
  • 定义Controller

hello.java

package com.uni.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class hello {
    @RequestMapping("/hello")
    public String hello(){
        return "hello,SpringBoot!";
    }
}
  • 编写引导类

HelloApplication.java

package com.uni;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}
  • 启动测试,访问 localhost:8080/hello

2.3 使用 IDEA2021 快速创建SpringBoot项目

springboot 子模块依赖父级本地包 springbootapplication依赖_maven_02

选择 SpringWeb

springboot 子模块依赖父级本地包 springbootapplication依赖_maven_03

标记项目的src/main下的java文件夹为 source(蓝色的文件夹),否则无法正常运行包下的Java类

springboot 子模块依赖父级本地包 springbootapplication依赖_spring_04

IDEA自动生成的pom依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.uni</groupId>
    <artifactId>demo02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo02</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.3 小结

  • SpringBoot 在创建项目时,使用jar的打包方式
  • SpringBoot的引导类是项目入口,运行main方法就可以启动项目
  • 使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样

3. SpringBoot 起步依赖原理分析


spring-boot-starter-parent中定义了各种技术的版本信息,组合了一套最优搭配的技术版本

在各种stater中,定义了完成该功能需要的坐标合计,其中大部分版本信息来自于父工程

工程继承parent,引入starter后,通过依赖传递,可以简单方便的获得需要的jar包,且不会存在版本冲突等问题。

4. SpringBoot配置


4.1 配置文件分类

SpringBoot是基于约定的,很多配置都有默认值,但若想使用自己的配置替换默认,可使用application.properties或者application.yml (/.yaml) 进行配置

  • properties
server.prot=8080
  • yml
server:
  port: 8080

在同一级目录下优先级(高 -> 低)为 properties -> yml -> yaml

4.2 yaml

yaml 全称是 yaml ain’t Markup Language 。 YAML是一种直观的能够被电脑识别的数据序列化格式,并且容器被人类阅读,容易和脚本语言交互,可被支持YAML库的不同的编程语言程序导入,比如:C/C++、Ruby、Python、Java、Perl等。

YML文件是以数据为核心的,比传统的XML方式更简洁, YAML文件的扩展名可用.yml或.yaml

  • properties
server.port=8080
server.address=127.0.0.1
  • xml
<server>
    <port>8080</port>
    <address>127.0.0.1</address>
</server>
  • yml
server:
    port: 8080
    address: 127.0.0.1

基本语法

  • 大小写敏感
  • 数据值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只需用使用空格(各个系统Tab对应的空格数目可能不同,导致层次混乱)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 表示注释,从这个字符已知到行尾,都会被解析器忽略

YAML : 数据格式

  • 对象(map): 键值对的集合
person:
  name: uni
# 行内写法
person: {name: uni}
  • 数组:一组按次序排列的值
address:
  - hangzhou
  - wenzhou
# 行内写法
address: [hangzhou, wenzhou]
  • 纯量: 单个的、不可再分的值
msg1: 'hello \n world'  # 单引忽略转义字符
msg2: "hello \n world"  # 双引识别转义字符

YAML: 参数引用

name : uni

person:
  name: ${name} # 引用上面定义的name值

YAML: 小结

配置文件类型

  • properties : 和以前一样
  • yml / yaml : 注意空格

yaml: 简洁、以数据为核心

  • 基本语法
  • 大小写敏感
  • 数值前必须有空格作为分隔符
  • 使用空格缩进表示层级关系,相同缩进表示同一级
  • 数据格式
  • 对象
  • 数组:使用"-" 表示数组每个元素
  • 参数引用
  • ${key}

4.3 读取配置文件内容

4.3.1 @Value

application.yml

name: uni

student:
  name: cc

address:
  - hangzhou
  - wenzhou

HelloController.java

package com.uni.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @Value("${name}")
    private String name_uni;

    @Value("${student.name}")
    private String name_stu;

    @Value("${address[0]}")
    private String addr;

    @RequestMapping("/hello")
    public void hello(){
        System.out.println("hello, I'm " + name_uni);
        System.out.println("I'm " + name_stu);
        System.out.println("城市: " + addr);
    }
}

4.3.2 Environment

用和之前相同的yml文件

HelloController.java

package com.uni.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Autowired
    private Environment env;

    @RequestMapping("/hello")
    public void hello(){
        System.out.println("hello, I'm " + env.getProperty("name"));
        System.out.println("I'm " + env.getProperty("student.name"));
        System.out.println("城市: " + env.getProperty("address[0]"));
    }
}

4.3.3 @ConfigurationProperties

此注解一个于标记某个类表示支持赋值配置文件里的内容

案例: 标记Student实体类

Student.java

package com.uni;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
    private String name;
    private int age;
    private String[] hobbys;
}

spring-boot的配置 application.yml

student:
  name: cc
  age: 21
  hobbys:
    - 跑步
    - 睡觉

HelloController.java

package com.uni.controller;

import com.uni.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @Autowired
    private Student student;
    @RequestMapping("/stu")
    public void stu(){
        System.out.println(student);
    }
}

启动application,访问 lcoalhost:8080/stu,终端的结果为:

Student(name=cc, age=21, hobbys=[跑步, 睡觉])

4.4 profile

作用:动态配置切换,解决Spring Boot应用开发,开发、测试、生产等不同环境下的配置切换问题

需要了解的内容:

  1. profile 配置方式
  • 多profile文件方式
  • yml多文档方式
  1. profile激活方式
  • 配置文件
  • 虚拟机参数
  • 命令行参数

4.4.1 多profile文件配置

springboot 子模块依赖父级本地包 springbootapplication依赖_spring_05

4.4.2 yml多文档方式

application.yml 配置文件中以三个横岗— 划分一个文档区域,比如:

---
server:
  port: 8081
---

案例:在一个yml文件中设置3个启动端口,并激活其中的1个服务器端口

application.yml

---
server:
  port: 8081
spring:
  config:
    activate:
      on-profile: dev
---
server:
  port: 8082
spring:
  config:
    activate:
      on-profile: test
---
server:
  port: 8083
spring:
  config:
    activate:
      on-profile: pro
---

spring:
  profiles:
    active: test

springboot 子模块依赖父级本地包 springbootapplication依赖_xml_06

4.4.3 通过JVM虚拟机配置激活yml文档

在IDEA设置Run/Debug Configurations中的 vm options参数

范例:激活yml里的test文档

-Dspring.profiles.active=test

其中test是yml里通过三个横杠设置的一个文档配置,如下:

---
server:
  port: 8082
spring:
  config:
    activate:
      on-profile: test
---

springboot 子模块依赖父级本地包 springbootapplication依赖_spring boot_07

springboot 子模块依赖父级本地包 springbootapplication依赖_maven_08

4.4.4 通过progarming参数激活yml文档

在IDEA设置Run/Debug Configurations中的 programming options参数

范例:

--spring.profiles.active=test

springboot 子模块依赖父级本地包 springbootapplication依赖_maven_09

4.4.5 通过命令行在执行jar包时激活yml文档

java -jar 打包后的.jar --spring.profiles.active=test

springboot 子模块依赖父级本地包 springbootapplication依赖_xml_10

4.4.6 总结

  • profile是用来完成不同环境下,配置动态切换功能的
  • profile配置方式
  • 多profile文件方式:提供多个配置文件,每个代表一种环境
  • application-dev.properties/yml 开发环境
  • application-test.properties/yml 测试环境
  • application-pro.properties/yml 生产环境
  • yml多文档方式
  • 在yml中使用 使用三个横杠— 分割不同配置
  • profile激活方式
  • 配置文件:在yml配置文件中 spring.profiles.active=dev
  • 虚拟机参数: 在VM opionts指定 -Dspring.profiles.active=dev
  • 命令行参数: java -jar xxx.jar --spring.profiles.active=dev

4.5 内部配置加载顺序

Springboot程序启动时,会从以下位置加载配置文件:

  • file: ./config/ : 当前目录下的/config目录下
  • file:./ : 当前项目的根目录
  • classpath:/config/: classpath的/config目录
  • classpath: / classpath的根目录

加载顺序为上文的排列顺序,高优先级配置的属性会生效

4.6 外部配置加载顺序

通过官网查看外部属性加载顺序

1. Default properties (specified by setting `SpringApplication.setDefaultProperties`).

2. [`@PropertySource`](https://docs.spring.io/spring-framework/docs/5.3.14/javadoc-api/org/springframework/context/annotation/PropertySource.html) annotations on your `@Configuration` classes. Please note that such property sources are not added to the `Environment` until the application context is being refreshed. This is too late to configure certain properties such as `logging.*` and `spring.main.*` which are read before refresh begins.

3. Config data (such as `application.properties` files).

4. A `RandomValuePropertySource` that has properties only in `random.*`.

5. OS environment variables.

6. Java System properties (`System.getProperties()`).

7. JNDI attributes from `java:comp/env`.

8. `ServletContext` init parameters.

9. `ServletConfig` init parameters.

10. Properties from `SPRING_APPLICATION_JSON` (inline JSON embedded in an environment variable or system property).

11. Command line arguments.

12. `properties` attribute on your tests. Available on [`@SpringBootTest`]
(https://docs.spring.io/spring-boot/docs/2.6.2/api/org/springframework/boot/test/context/SpringBootTest.html) and the [test annotations for testing a particular slice of your application](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#features.testing.spring-boot-applications.autoconfigured-tests).

13. [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/5.3.14/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations on your tests.

14. [Devtools global settings properties](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#using.devtools.globalsettings) in the `$HOME/.config/spring-boot` directory when devtools is active.

Config data files are considered in the following order:

1. [Application properties](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#features.external-config.files) packaged inside your jar (`application.properties` and YAML variants).

2. [Profile-specific application properties](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#features.external-config.files.profile-specific) packaged inside your jar (`application-{profile}.properties` and YAML variants).

3. [Application properties](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#features.external-config.files) outside of your packaged jar (`application.properties` and YAML variants).

4. [Profile-specific application properties](https://docs.spring.io/spring-boot/docs/2.6.2/reference/htmlsingle/#features.external-config.files.profile-specific) outside of your packaged jar (`application-{profile}.properties` and YAML variants).

其中第十一种,在执行jar包时通过命令行指定

java -jar xxx.jar --server.port=8082

官网7.2.3 的example

$ java -jar myproject.jar --spring.config.location=\
    optional:classpath:/default.properties,\
    optional:classpath:/override.properties

最常用的还是在jar包的同级目录下创建application.properties,比它优先级更高的是同级目录的config文件夹里的properties

可用于修改jar包内部一些配置,而且不影响项目其他的配置,特别方便

5. 总结


通过本次的学习,快速入门了 SpringBoot Web,简单的实现了 HelloWorld,同样是Web开发,跟之前的 Tomcat 部署相比,SpringBootWeb方便许多,只需要执行一个带有@SpringBootApplication注解的类,而且调用了SpringbootTestApplication方法就能启动一个web程序,而且不用配置web.xml

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootTestApplication.class, args);
    }
}

除此之外,笔者第一次接触了yml、yaml、propertries多种配置文件混合使用的情况,它们之间的优先级是 p > yml > yaml

通过Srping的注解方式简写了一个Controller层的类,之前都是继承一个HttpServlet然后使用@WebServlet进行编写,现在感觉方便很多,因为可以在同一个类里写多个方法用于响应不同地址的请求。

@RestController
public class hello {
    @RequestMapping("/hello")
    public String hello(){
        return "hello,SpringBoot!";
    }
}

起步依赖的部分有一点蒙,这应该属于Maven的知识,笔者没有系统学过Maven,现在暂时的理解就是它能像Java类一样去继承一个父类,然后Maven也可以实现这种继承,所以新建的SpringBootWeb项目里的pom.xml看起来较为简洁,其原因大概就是继承了封装好的一个Maven依赖,然后SpringBoot已经设计好了所有的依赖,现在可以直接使用。

综合以上,SpringBoot的使用并不复杂,但是对于其原理的理解则还需要进一步深入,同时需要花更多时间来熟练应用。