SpringBoot 从配置文件中获取数据的三种方式
SpringBoot 是基于 Spring 的简化配置方案,不是对 Spring 技术的升级,本质上是提供了一种快速使用 Spring 的开发方式。
SpringBoot 基于约定优于配置的思想,提供了大量的起步依赖,能够让开发人员快速搭建 Spring 项目,减少在配置与业务之间的思维切换,从而可以全身心的投入到逻辑业务的代码开发中,从而大大提高了开发的效率。
SpringBoot 的起步依赖本质上就是依靠 Maven 将具备某种功能的 jar 包整理到一起,并提供了默认的配置,从而省去了导入 jar 包、解决 jar 包之间冲突、编写大量配置的繁琐工作,进而提高开发效率。
本篇博客主要介绍从 SpringBoot 的 yml 配置文件中,获取数据的 3 种方式,博客最后会提供源代码。
有关 SpringBoot 的详细介绍,请参考官网:https://spring.io/projects/spring-boot
一、搭建项目
新建一个 SpringBoot 项目,选择 Spring Initializr 选项,注意需要联网。
选择 Web 下的 Spring Web 依赖项:
本博客的 Demo 搭建后的最终结构如下所示:
SpringBoot 项目创建完成后,其 pom 文件内容如下:
<?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.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jobs</groupId>
<artifactId>springboot_getdata</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_getdata</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>
<!--下面这个依赖,不是项目创建后自动生成的,是人工添加的-->
<!--解决 IDEA 编写与配置项对应的实体类时,文件上方总是出现红色提示的问题-->
<!--导入该依赖后,在编写配置文件时,如果用到了实体类的属性,会有智能提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、yml 配置文件
SpringBoot 的配置文件名称,约定必须以 application 开头,支持 3 种后缀名:properties 、yml、yaml 。
如果在 resources 目录下同时存在 3 后缀的配置文件,且配置了相同的键值对的话,那么所配置的键值对最终生效的优先级顺序为 properties > yml > yaml 。
一般情况下,我们经常在 SpringBoot 中使用以 yml 为后缀名的配置文件,即 application.yml 。
yml 配置文件编写配置的注意事项为:
- 配置项的 key 和 value 都是大小写敏感
- value 值前边必须至少有一个空格作为分隔符(多个空格跟一个空格的效果是一样的)
- 使用缩进表示层级关系,缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- 缩进不允许使用Tab键,只允许使用空格,因为各个系统 Tab 对应的空格数目可能不同,有可能导致混乱
- ''#" 号表示注释,从这个字符一直到行尾,都会被解析器忽略
如果采用 IDEA 开发工具来编写 yml 文件的话,那么可以在缩进时使用 Tab,因为 IDEA 开发工具会帮助我们转换为空格。
本博客在 resource 下的 application.yml 文件的内容如下:
name: 候胖胖
age: 40
hobby: 瞎逛游,开玩笑,踢毽子
employee:
name: 任肥肥
age: 38
hobby:
- 睡觉
- 吃饭
- 摸鱼
remark1: '${name} \n 喜欢踢毽子'
remark2: "${employee.name} \n 喜欢上班摸鱼"
三、代码细节
首先我们先看一下启动引导类,内容如下:
package com.jobs.springboot_getdata;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
//如果 controller 和 domain 跟启动类在同一个包或子包中,则不需要添加扫描配置
//因为 springboot 默认扫描启动类所在的包及其子包下所有的注解
@ComponentScan("com.jobs")
public class SpringbootGetdataApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootGetdataApplication.class, args);
}
}
本博客中的 Demo 故意没有把 controller 和 domain 这两个包放在 springboot_getdata 包下。
在 com.jobs.springboot_getdata 包下的 SpringbootGetdataApplication 类是该 SpringBoot 项目的启动类,如果 controller 和 domain 这两个包跟启动类在同一包下,或者在启动类所在的包的子包下的话,那么启动类上面就不需要配置 @ComponentScan 扫描包注解,因为默认情况下 SpringBoot 扫描启动类所在的包及其子包下所有的注解。
本篇博客实现的功能是:使用 3 种方式,从 yml 配置文件中,读取所配置的数据。
第一种方式:采用 @Value 注解配置读取的 yml 中的 key
第二种方式:采用 Evironment 环境变量进行获取
第三种方式:新建一个实体类,建立实体类属性与 yml 配置项的对应关系
具体代码在 TestController 类中,内容如下:
package com.jobs.controller;
import com.jobs.domain.Employee;
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;
import java.util.Arrays;
import java.util.List;
@RestController
public class TestController {
//------------------------------------------
//通过 @Value 注解获取 yml 中配置的值
@Value("${name}")
private String name;
@Value("${age}")
private int age;
//使用英文逗号分隔的字符串,可以直接转换为数组
@Value("${hobby}")
private String[] hobby;
@Value("${employee.name}")
private String e_name;
@Value("${employee.age}")
private int e_age;
//通过 @Value 注解,对于使用横杠表示的数组,无法直接获取整个数组
//只能通过数组的下标,获取具体的一个数组元素
@Value("${employee.hobby[0]}")
private String e_hobby0;
@RequestMapping("/getdata1")
public String getData1() {
//通过 @Value 注解,获取 yml 配置文件中的对应名称的值
StringBuilder sb = new StringBuilder();
sb.append(name).append("<br/>");
sb.append(age).append("<br/>");
sb.append(Arrays.toString(hobby)).append("<br/>");
sb.append(e_name).append("<br/>");
sb.append(e_age).append("<br/>");
sb.append(e_hobby0);
System.out.println(sb.toString().replace("<br/>","\n"));
return sb.toString();
}
//------------------------------------------
//通过 Environment 环境对象,获取 yml 中配置的值
@Autowired
private Environment env;
@RequestMapping("/getdata2")
public String getData2()
{
//通过 Environment 环境对象,获取 yml 中配置的值
String name2 = env.getProperty("name");
String e_name2 = env.getProperty("employee.name");
System.out.println(name2);
System.out.println(e_name2);
//在 yml 的配置中,可以通过 ${变量名} 引用大括号中的变量所配置的值
String remark1 = env.getProperty("remark1");
String remark2 = env.getProperty("remark2");
//对于单引号包裹的字符串,不会处理转义字符
System.out.println(remark1);
//对于双引号包裹的字符串,会对转义字符进行处理
System.out.println(remark2);
return "请在 IDEA 控制台上,查看运行结果";
}
//------------------------------------------
//通过实体对象,获取 yml 中配置的值,需要创建一个实体类与 yml 中相关配置节对应
//在实体类中,可以获取到横杠配置的数组
@Autowired
private Employee emp;
@RequestMapping("/getdata3")
public String getData3()
{
System.out.println(emp);
System.out.println("姓名:"+emp.getName());
System.out.println("年龄:"+emp.getAge());
System.out.println("爱好:"+Arrays.toString(emp.getHobby()));
return "请从 IDEA 的控制台,查看通过实体类对象获取的 yml 配置值";
}
}
在上面的代码中,第三种实现方式,要求创建一个实体类 Employee ,其属性要与 yml 中的 employee 下面的 name、age、hobby 配置项对应起来,下面列出 Employee 实体类的内容:
package com.jobs.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
//使用 prefix 指定对应的 yml 配置项
//这里将 prefix 配置为 employee ,所以实体类读取的是 employee 级别下的相应数据
//如果没有配置 prefix 的话,那么读取的是读取的就是最顶层级的 name,age 和 hobby
@ConfigurationProperties(prefix = "employee")
public class Employee {
//姓名
private String name;
//年龄
private int age;
//爱好
private String[] hobby;
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 String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", hobby=" + Arrays.toString(hobby) +
'}';
}
}
在上面的代码中,当你在 Employee 类上配置了 @ConfigurationProperties 注解后,会发现 IDEA 上方多了一个红条提示,看起来挺难受的,为了解决这个问题,只需要在 pom 文件中添加一个依赖即可,具体如下:
<!--下面这个依赖,不是项目创建后自动生成的,是人工添加的-->
<!--解决 IDEA 编写与配置项对应的实体类时,文件上方总是出现红色提示的问题-->
<!--导入该依赖后,在编写配置文件时,如果用到了实体类的属性,会有智能提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
OK,在完成上面代码的编写后,启动 SpringBoot 程序,默认是 8080 端口,访问 TestController 下提供的 3 个接口进行测试即可,如果想要修改 SpringBoot 端口,只需要在 yml 配置中,增加一下配置即可,比如配置为 8888 端口:
server:
port: 8888
到此为止,已经介绍完毕 SpringBoot 从 yml 配置文件中,读取数据的 3 种方式,大家可根据实际情况选择最佳方式。
本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_getdata.zip