SpringBoot(二) 文件结构和配置详解

SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程

简介

SpringBoot 虽然干掉了 XML 但未做到 零配置,它体现出了一种 约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。 一般情况下默认的配置足够满足日常开发所需,但在特殊的情况下,我们往往需要用到自定义属性配置、自定义文件配置、多环境配置、修改默认端口等一系列功能。不用担心,这些 SpringBoot 都替我们考虑好了,我们只需要遵循它的规则配置即可

项目文件结构

新建的Springboot项目的文件结构如下:

结构

1
2
3
4
5
6
7
8
9
10
|-springboot2-02(项目名称)
| - src
| | - main
| | | - java
| | | - resources
| | | | - static
| | | | - templates
| | - test
| | | - java
| - pom.xml

简单说明

  1. springboot2-02:项目名称
  2. src/main/java:目录下防止所有java文件(源代码文件)
  3. src/main/resources:防止所有配置文件、页面文件、静态资源文件等
  4. src/test/java:所有java测试文件

自定义属性配置

Springboot默认支持两种配置文件类型:.properties.yml
当我们创建一个springboot项目的时候,系统默认会为我们在src/main/java/resources目录下创建一个application.properties。个人习惯,我会将application.properties改为application.yml文件。

application.yml

YAML简单说明

今后我们修改application.properties文件配置为application.yml配置。.yml配置文件与.properties配置要更清晰更有层次感,可以很明了的看懂配置信息。

注意:使用 .yml 时,属性名的值和冒号中间必须有空格,如name: Ray 正确,name:Ray就是错的。

1
2
3
my:
name: Ray
age: 18

注意:Springboot会自动在src/main/resources/目录下找application.properties或application.yml配置文件,找到后将应用此配置文件中的配置,否则使用其默认值。这两种类型的配置文件有其一即可,也可两者并存。

默认情况下,.properties 配置文件的优先级更高,如果在application.properties 中配置了server.port=9090 同时也在application.yml 中配置了server: port: 9091 时,系统将使用 .properties中的9090端口。

其次定义 MyProperties1.java 文件,用来映射我们在 application.yml 中的内容,这样一来我们就可以通过操作对象的方式来获得配置文件的内容了

MyProperties1.java

使用@ConfigurationProperties 读取多个属性

使用方法:@ConfigurationProperties(prefix = "my")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.ray.properties;

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

/**
* @author Ray
* @date 2018/7/22 0022
*/
@Data
@Component
@ConfigurationProperties(prefix = "my")
public class MyProperties1 {

private String name;
private int age;

}

出现红框!

解决: 为了让 Spring Boot 更好的生成配置元数据文件,我们需要添加如下依赖

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

该依赖可以不添加,但是在 IDEA 和 STS 中不会有属性提示,没有提示的配置就跟你用记事本写代码一样苦,出个问题弄哭你

接下来就是定义我们的 PropertiesController 用来注入 MyProperties1 测试我们编写的代码,值得注意的是 Spring4.x 以后,推荐使用构造函数的形式注入属性…

PropertiesController.java

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
/**
* @author Ray
* @date 2018/7/22 0022
*/
@RequestMapping("/properties")
@RestController
public class PropertiesController {

private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesController.class);

private final MyProperties1 myProperties1;

/**
* 构造函数形式注入属性
* @param myProperties1
*/
@Autowired
public PropertiesController(MyProperties1 myProperties1) {
this.myProperties1 = myProperties1;
}

@GetMapping("/one")
public MyProperties1 myProperties1(){
LOGGER.info("=================================================================");
LOGGER.info(myProperties1.toString());
LOGGER.info("=================================================================");
return myProperties1;
}
}

打开浏览器,输入如下地址: http://localhost:8080/properties/one,观察浏览器和控制台,监听到如下内容则表示程序正确

1
2
3
4
5
6
2018-07-22 11:56:27.505  INFO 16376 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-07-22 11:56:27.505 INFO 16376 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-07-22 11:56:27.521 INFO 16376 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 16 ms
2018-07-22 11:56:27.551 INFO 16376 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : =================================================================
2018-07-22 11:56:27.552 INFO 16376 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : MyProperties1(name=Ray, age=18)
2018-07-22 11:56:27.552 INFO 16376 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : =================================================================

你现在能大概猜到为什么SpringBoot 应用能够根据默认属性来自动配置数据源了吧?因为内置的数据源类DataSourceProperties通过@ConfigurationProperties(prefix = “my”)读取到了我们在配置文件填写的数据源信息,然后通过DataSourceAutoConfiguration 创建了数据源Bean和进行了相关初始化配置。

自定义文件配置

定义一个名为 my2.properties 的资源文件,自定义配置文件的命名不强制 application 开头
注意: my2.yml 是无法识别的文件

1
2
3
my2.name=Ray
my2.age=18
my2.email=343509740@qq.com

其次定义 MyProperties2.java 文件,用来映射我们在 my2.properties 中的内容。

MyProperties2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author Ray
* @date 2018/7/22 0022
*/
@Data
@Component
@PropertySource("classpath:my2.properties")
@ConfigurationProperties(prefix = "my2")
public class MyProperties2 {

private String name;
private int age;
private String email;
}

接下来在 PropertiesController 用来注入 MyProperties2 测试我们编写的代码

PropertiesController.java

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
/**
* @author Ray
* @date 2018/7/22 0022
*/
@RequestMapping("/properties")
@RestController
public class PropertiesController {

private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesController.class);

private final MyProperties1 myProperties1;
private final MyProperties2 myProperties2;

/**
* 构造函数形式注入属性
* @param myProperties1
*/
@Autowired
public PropertiesController(MyProperties1 myProperties1, MyProperties2 myProperties2) {
this.myProperties1 = myProperties1;
this.myProperties2 = myProperties2;
}

@GetMapping("/one")
public MyProperties1 myProperties1(){
LOGGER.info("=================================================================");
LOGGER.info(myProperties1.toString());
LOGGER.info("=================================================================");
return myProperties1;
}

@GetMapping("/two")
public MyProperties2 myProperties2(){
LOGGER.info("=================================================================");
LOGGER.info(myProperties2.toString());
LOGGER.info("=================================================================");
return myProperties2;
}
}

打开浏览器,输入如下地址: http://localhost:8080/properties/two,观察浏览器和控制台,监听到如下内容则表示程序正确

1
2
3
4
5
6
2018-07-22 12:06:00.570  INFO 6348 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-07-22 12:06:00.570 INFO 6348 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-07-22 12:06:00.587 INFO 6348 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 16 ms
2018-07-22 12:06:00.605 INFO 6348 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : =================================================================
2018-07-22 12:06:00.605 INFO 6348 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : MyProperties2(name=Ray, age=18, email=343509740@qq.com)
2018-07-22 12:06:00.605 INFO 6348 --- [nio-8080-exec-1] c.r.s.controller.PropertiesController : =================================================================

多环境化配置

在真实的应用中,常常会有多个环境(如:开发,测试,生产等),不同的环境数据库连接都不一样,这个时候就需要用到spring.profile.active 的强大功能了,它的格式为 application-{profile}.properties,这里的 application 为前缀不能改,{profile} 是我们自己定义的。

创建 application-dev.propertiesapplication-test.propertiesapplication-prod.properties,内容分别如下

application-dev.properties

1
server.servlet.context-path=/dev

application-test.properties

1
server.servlet.context-path=/test

application-prod.properties

1
server.servlet.context-path=/prod

在 application.yml 配置文件中写入 spring.profiles.active=dev

application.yml

1
2
3
spring:
profiles:
active: dev

此时,我们再次访问:
http://localhost:8080/properties/two
已经没用了,因为我们设置了它的 context-path=/dev ,所以新的路径应该是:
http://localhost:8080/dev/properties/two
由此,可以看出来我们激活不同的配置读取的属性值是不一样的

修改默认端口

SpringBoot 默认使用的端口是: 8080
修改端口:

1
2
server:
port: 8089

访问地址:
http://localhost:8089/dev/properties/two
8089端口已生效

总结

1.掌握@ConfigurationProperties@PropertySource 等注解的用法及作用
2.掌握编写自定义配置

-------------- 本文结束  感谢您的阅读 --------------