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 选项,注意需要联网。

image

选择 Web 下的 Spring Web 依赖项:

image

本博客的 Demo 搭建后的最终结构如下所示:

image

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

posted @ 2022-07-27 19:59  乔京飞  阅读(15447)  评论(0编辑  收藏  举报