SpringBoot

SpringBoot是一个全新开源的轻量级框架。它基于Spring4.0设计,进一步简化了Spring的配置,更加简单的完成整个搭建和开发。

微服务架构

https://martinfowler.com/articles/microservices.html

第一个SpringBoot程序

可以去官网去创建一个springboot的项目(用idea自带创建也是通过官网创建的),配置什么的自己选择,注意要添加一个Spring Web的依赖,不然不能用作Web开发,然后GENERATE下载项目到本地,用idea导入项目就可以了。

在项目自带的Application类的同级目录下(一定要同级目录,不然SpringBoot无法扫描到你写的类)创建包和类,现创建一个Hello的类。

1
2
3
4
5
6
7
8
9
@Controller
@ResponseBody//将返回的数据写给浏览器,对象就会返回JSON数据
//这两个由@RestController替换,因为这两个注解已经被RestController注解包括了。
public class Hello {
@GetMapping("/hello")
public String hello(){
return "Hello World!";
}
}

然后通过Application类来运行,然后打开你的http://localhost:8080/hello就能看到HelloWorld了。

SpringBoot程序详解

分析一下我们的第一个SpringBoot程序。

Pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yw</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>My first springboot demo</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<!--Web场景启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

</dependencies>
<!--打包工具-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

  1. 父项目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!--Springboot的父项目-->
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!--点进去发现还有一个父项目-->
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.4.RELEASE</version>
    </parent>
    <!--
    点进去看到有很多properties,这些都是依赖的版本,即这个父项目管理了所有用到的依赖的版本,这就是为什么导入依赖时候不用声明版本号的原因。
    -->
  2. 导入的Spring Web的依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    <!--spring-boot-starter-web里的内容-->
    <?xml version="1.0" encoding="UTF-8"?>
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <!-- This module was also published with a richer model, Gradle metadata, -->
    <!-- which should be used instead. Do not delete the following line which -->
    <!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
    <!-- that they should prefer consuming it instead. -->
    <!-- do_not_remove: published-with-gradle-metadata -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.4.RELEASE</version>
    <name>spring-boot-starter-web</name>
    <description>Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container</description>
    <url>https://spring.io/projects/spring-boot</url>
    <organization>
    <name>Pivotal Software, Inc.</name>
    <url>https://spring.io</url>
    </organization>
    <licenses>
    <license>
    <name>Apache License, Version 2.0</name>
    <url>https://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
    </licenses>
    <developers>
    <developer>
    <name>Pivotal</name>
    <email>info@pivotal.io</email>
    <organization>Pivotal Software, Inc.</organization>
    <organizationUrl>https://www.spring.io</organizationUrl>
    </developer>
    </developers>
    <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection>
    <developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git</developerConnection>
    <url>https://github.com/spring-projects/spring-boot</url>
    </scm>
    <issueManagement>
    <system>GitHub</system>
    <url>https://github.com/spring-projects/spring-boot/issues</url>
    </issueManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.9.RELEASE</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.9.RELEASE</version>
    <scope>compile</scope>
    </dependency>
    </dependencies>
    </project>

spring-boot-starter,SpringBoot的场景启动器。那什么是场景启动器呢?在SpringBoot框架中,开发者已经帮我们模拟了很多个使用SpringBoot的开发场景,并将这些场景需要的依赖和配置全部写入到这些场景启动器当中。比如我们现在是开发web的场景,我们就导入了这个Spring Web的依赖,主要就是这个spring-boot-starter-web的web场景启动器,里面都是我们开发web需要的依赖以及一些配置。

主程序

1
2
3
4
5
6
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}

@SpringBootApplication这个注解标注了这是SpringBoot的主配置类,SpringBoot通过这个主配置类的main方法来启动这个SpringBoot的应用。查看里面的源码就会发现这个注解是由很多注解组成的,下面详细分析一下。

1
2
3
4
5
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

@SpringBootConfiguration

这个注解表示这个类是一个SpringBoot的配置类,点开里面发现还有个@Configuration注解,这个注解表示这是个Spring的配置类。

1
2
@Configuration
public @interface SpringBootConfiguration {

在点开就发现了这个@Component,所以发现这个配置类是容器的一个组件。

1
2
@Component
public @interface Configuration {

@EnableAutoConfiguration

这个注解告诉了SpringBoot要开启自动配置功能。

1
2
3
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

@Import(AutoConfigurationImportSelector.class)这是导入组件的选择器,会给容器导入很多这个场景所需要的所有组件并配置号这些组件。

@AutoConfigurationPackage这个注解表示自动配置包,点进去发现有一个这样的注解

1
@Import(AutoConfigurationPackages.Registrar.class)

这个注解是Spring的底层注解,@Import指定了AutoConfigurationPackages.Registrar.class这个类给容器导入一些组件。

所以这个@EnableAutoConfiguration就是将主配置类同目录下的包与类的所有组件扫描到Spring容器里面,这就是为什么一定要在同目录下创建包与类,因为不同目录就不会扫描得到。

Resource文件夹

  1. static文件夹
    保存静态资源的文件夹,比如js,css文件等。

  2. templates文件夹
    保存模板页面的文件夹,因为SpringBoot默认jar包嵌入式的Tomcat,所以不支持JSP页面,所以需要用到模板引擎来配置页面。

  3. application.properties(application.yml)
    SpringBoot的配置文件(名字是固定的不能修改),因为SpringBoot已经帮我们配置好了很多配置,想要修改这些默认配置就需要在这个配置文件自己修改,这个配置文件由两种形式,properties和yml形式。

    1. application.properties的格式是 key=value
      子配置就用点,比如service下的port配置就表示为service.port=value
    2. application.yml的格式是 key: value 注意有空格,因为yml文件对空格很敏感,
      具体语法可参照YAML语法,之后就用yaml的这种格式来写配置文件

配置文件值的注入

首先先写个需要注入值的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@Component
@ConfigurationProperties(prefix = "user")
public class User {
private String name;
private int age;
private Date birth;
private Boolean happy;
private Map<String,Object> family;
private List<Object> hobby;
private Dog dog;

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Date getBirth() {
return birth;
}

public void setBirth(Date birth) {
this.birth = birth;
}

public Boolean getHappy() {
return happy;
}

public void setHappy(Boolean happy) {
this.happy = happy;
}

public Map<String, Object> getFamily() {
return family;
}

public void setFamily(Map<String, Object> family) {
this.family = family;
}

public List<Object> getHobby() {
return hobby;
}

public void setHobby(List<Object> hobby) {
this.hobby = hobby;
}

public Dog getDog() {
return dog;
}

public void setDog(Dog dog) {
this.dog = dog;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", happy=" + happy +
", hobby=" + hobby +
", family=" + family +
", dog=" + dog +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Component
public class Dog {
private String name;
private int age;

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
  1. @Component表示这是spring的组件,会被注入到spring的容器中进行管理
  2. @ConfigurationProperties(prefix = “user”)表示绑定配置文件中的user的配置,这样就可以进行值的注入了

然后导入一个配置文件处理器的依赖(不导入会爆红虽然没影响),可以去配置文件注入值了。

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

这样就可以成功的将值注入了,可以去测试类进行一下测试。

1
2
3
4
5
6
7
8
9
@SpringBootTest
class DemoApplicationTests {
@Autowired
User user; //其实不一定要与配置类中的名称一致,user01也能读取出值
@Test
void contextLoads() {
System.out.println(user);
}
}

得到答案

1
User{name='Yw', age=20, birth=Wed Oct 21 00:00:00 CST 2020, happy=true, hobby=[play, game], family={father=yww1, mother=yww2}, dog=Dog{name='wwangwang', age=3}}

导入文件资源

@PropertySource

在上述的示例当中,要是总是把注入的值都加进全局的配置文件中就会显得很乱,所以可以新建一个文件在通过@PropertySource标签导入进去也可以实现值的注入,这样application.properties中就可以不用写user的值了,值都写在user.properties即可。

1
2
3
4
@Component
@ConfigurationProperties(prefix = "user")
@PropertySource(value = {"classpath:user.properties"})
public class User {

注意@PropertySource这个标签导入的是properties的文件,yml文件会出问题。

@ImportResource

这个标签是用来导入spring的配置文件到springBoot中的(即xml格式)

1
@ImportResource(locations = {"classpath:beans.xml"})

@Bean

这个标签的功能与@ImportResource类似,也是为了导入配置,给容器添加一个组件的。比如写一个配置类。

1
2
3
4
5
6
7
@Configuration	//表示这个类是一个配置类,就像是一个spring的配置文件
public class Config {
@Bean //将方法的返回值注入到容器之中,类似spring配置中
public Hello hello(){
return new Hello();
}
}
  1. @Configuration 表示这个类是一个配置类,就像是一个spring的配置文件
  2. @Bean 将方法的返回值注入到容器之中,类似spring配置中注入bean的操作,方法名就是这个bean的id。

Profile

properties的多文档

首先就是主要的配置文件application.properties,创建多文档的方式就是按照application-[name].properties的形式命名创建在resources目录下。就比如我创建了一个测试环境的配置,命名为application-dev.properties

yaml的多文档

这个就很方便了,直接在application.yml中就可以创建多个文档配置了。只要通过---就能将配置文件分成不同的文档配置,通过spring.profiles: [name]这个配置就能为这个文档配置取个名字了。

1
2
3
4
5
6
7
8
server:
port: 8085
---
server:
port: 8086
spring:
profiles: dev
---

激活指定的Profile

properties

在主配置文件,即application.properties下增加这个配置,就可以激活相应名字的文档配置文件。

1
spring.profiles.active=dev

yaml

yaml形式也是通过这个配置spring.profiles.active=dev,就能激活相应名字的文档配置文件。

1
2
3
4
5
6
7
8
9
10
server:
port: 8085
spring:
profiles:
active: dev
---
server:
port: 8086
spring:
profiles: dev

共同的激活方式

  1. 命令行
    比如在打了jar包之后,在命令行运行jar包的时候增加配置就能激活指定配置文件生效。

    1
    java -jar ---.jar --spring.profiles.active=dev
  2. 虚拟机参数
    修改虚拟机参数也可以修改。

    1
    -Dspring.profiles.active=dev

配置文件的优先级

配置文件的优先级由高到低分别为:

  1. 项目路径下的config文件夹中的配置文件
  2. 项目路径下的配置文件
  3. 资源路径下的config文件夹中的配置文件
  4. 资源路径下的配置文件

springboot会通过优先级来加载配置文件,要是有不止一个配置文件,springboot也是会全部加载这些配置文件。对于设置了相同的配置,优先级高的配置文件设置的就会覆盖掉优先级低的配置文件的设置。就比如每个配置文件都设置了不同的打开端口,就会以优先级高的配置文件的为准。其他不冲突的配置也是生效的。