聊一聊springboot项目配置参数的三个来源

大家好,我是G探险者,今天我们聊一聊,springboot的参数的三个来源。 平时我们部署项目后,难免都会进行一下配置修改,有的是在修改环境变量,有的是直接通过命令行参数进行修改,有的是直接改,配置文件,那么这三种不同来源的参数修改,都是如何生效的,以及他们之间的一些区别是啥样的,下面我就写问题聊一聊。

1. 配置参数的三个来源

当配置一个应用程序时,可以从多个来源获取配置参数。下面是三个常见的配置参数来源:

  1. 命令行参数: 命令行参数是在启动应用程序时通过命令行传递的参数。这些参数可以用来修改应用程序的行为或配置。在Java中,可以使用main()方法中的args参数来接收命令行参数。例如,以下命令行启动应用程序并传递参数:

    java MyApp --param1=value1 --param2=value2
    

    在这个例子中,--param1=value1--param2=value2就是命令行参数。应用程序可以通过解析命令行参数来获取这些值,并根据需要进行配置。

  2. 环境变量: 环境变量是在操作系统级别设置的全局变量。它们包含有关操作系统和正在运行的应用程序的信息。应用程序可以读取环境变量以获取配置参数。在大多数操作系统中,可以使用特定的命令来设置和获取环境变量。例如,在Linux和Mac上,可以使用export命令设置环境变量,如下所示:

    export MY_VAR=value
    

    应用程序可以通过读取MY_VAR环境变量来获取值。

  3. Spring Boot自带的配置文件(application.propertiesapplication.yml): Spring Boot是一个用于构建Java应用程序的框架,提供了许多便捷的配置方式。其中一种方式是使用application.propertiesapplication.yml配置文件来定义应用程序的属性。这些文件通常位于应用程序的类路径下,可以包含键值对或层级结构的配置。应用程序在启动时会读取这些文件,并将其中定义的配置参数应用到应用程序中。例如,以下是一个application.properties文件的示例:

    server.port=8080
    database.url=jdbc:mysql://localhost:3306/mydb
    

    在这个例子中,server.portdatabase.url是配置参数的键,8080jdbc:mysql://localhost:3306/mydb是对应的值。Spring Boot应用程序将读取这些值,并相应地配置嵌入式服务器的端口和数据库连接。

这些来源可以单独或组合使用,以提供应用程序的配置参数。在实际开发中,可以根据需要选择最适合的配置方式。例如,命令行参数适合临时修改配置,环境变量适合在不同环境中设置不同的配置,而配置文件则适合将配置集中管理并与代码一起打包部署。

2. 不通来源的参数配置区别

我们先通过以下这个表格直观的看一下,三种不同来源(命令行参数、环境变量和Spring Boot自带的配置文件)有以下区别:

来源用途和灵活性优先级和覆盖可读性和管理
命令行参数临时调整配置,特定操作最高优先级,覆盖其他来源易于理解和管理,但参数较多时可能冗长
环境变量在不同环境中设置不同配置高于配置文件,低于命令行参数需要操作系统级别的设置和管理
Spring Boot自带的配置文件长期配置,集中管理低于命令行参数和环境变量可读性高,易于维护和理解

请注意,以上表格提供了一般性的对比,并且在特定情况下可能会有例外或变化。对于每个项目和场景,最佳选择可能会有所不同,取决于特定的要求和偏好。

  1. 用途和灵活性:

    • 命令行参数:命令行参数通常用于在每次启动应用程序时提供临时的、特定于该次运行的配置。这些参数可以根据需要进行更改,因此在不同的运行实例中可以使用不同的参数。命令行参数对于临时调整配置或执行特定操作非常有用。但是,它们不适合长期或全局配置。
    • 环境变量:环境变量是在操作系统级别设置的全局变量。它们可以在不同的应用程序和进程之间共享,并且可以用于配置各种应用程序。环境变量通常用于在不同的环境(例如开发、测试、生产)之间设置不同的配置。它们提供了一种灵活且易于配置的方式,可以根据不同的部署环境进行调整。
    • Spring Boot自带的配置文件:Spring Boot的配置文件提供了一种在应用程序内部集中管理配置的方法。配置文件可以包含多个属性,并且支持层级结构。这种方式适合于将配置与代码分离,以便更好地组织和维护配置。配置文件通常与应用程序一起打包,并在应用程序启动时被读取和应用。它们适用于长期配置,不容易在每次运行时进行更改。
  2. 优先级和覆盖:

    • 命令行参数:命令行参数通常具有最高优先级。如果在命令行参数中指定了某个配置,它将覆盖其他来源中的相同配置。这使得可以通过命令行参数临时覆盖应用程序的默认配置。
    • 环境变量:环境变量的优先级通常高于Spring Boot的配置文件。如果在环境变量中设置了某个配置,它将覆盖配置文件中的相同配置。这允许在不修改配置文件的情况下,通过设置环境变量来更改应用程序的配置。
    • Spring Boot自带的配置文件:配置文件中的配置参数提供了默认值,但可以通过命令行参数或环境变量进行覆盖。如果在配置文件中定义了某个配置,但在命令行参数或环境变量中也有相同的配置,后者将覆盖前者。
  3. 可读性和管理:

    • 命令行参数:命令行参数是直接在启动命令中指定的,因此它们在启动命令中是可见的。这使得命令行参数易于理解和管理,因为可以清楚地看到应用程序在启动时使用了哪些参数。然而,当需要配置大量参数时,命令行参数可能会变得冗长和难以管理。
    • 环境变量:环境变量是在操作系统级别设置的,可以在操作系统中进行管理。这使得环境变量的设置和管理相对容易,可以在不同的部署环境中轻松配置和更改变量。然而,环境变量的设置和值不直接与应用程序相关联,因此在应用程序代码中可能需要额外的逻辑来读取和处理这些变量。
    • Spring Boot自带的配置文件:Spring Boot的配置文件可以集中管理应用程序的配置,并具有良好的可读性和可维护性。配置文件使用键值对或层级结构的方式组织配置参数,使得它们更易于理解和管理。此外,配置文件可以通过注释和文档来提供参数的说明,进一步提高可读性。配置文件与应用程序代码直接相关,因此在代码中可以直接使用配置参数,无需额外的处理。

总结起来,命令行参数适合临时修改和调试配置,环境变量适合在不同环境中设置不同的配置,而Spring Boot自带的配置文件适合集中管理和维护应用程序的配置。 它们各自具有不同的优点和适用场景,可以根据具体需求选择最合适的配置方式。

3. 不同来源的参数是如何被springboot识别并解析的?

在Spring Boot中,配置参数的识别和解析是通过Spring Boot的配置处理机制完成的。这个机制可以自动识别并解析来自命令行参数、环境变量和配置文件的配置参数。以下是对每种来源的配置参数在Spring Boot中的处理方式:

  1. 命令行参数:

    • Spring Boot使用org.springframework.boot.ApplicationArguments接口来处理命令行参数。可以通过在Spring Bean中注入ApplicationArguments来访问命令行参数。

    • 可以使用getOptionValues(String name)方法获取指定名称的选项值,其中name是命令行参数的名称。

    • 例如,假设有一个命令行参数--param1=value1,可以使用以下方式在Spring Bean中获取该参数的值:

      @Autowired
      private ApplicationArguments applicationArguments;
      
      public void someMethod() {
          List<String> param1Values = applicationArguments.getOptionValues("param1");
          // 使用param1Values进行后续处理
      }
      
  2. 环境变量:

    • Spring Boot使用org.springframework.core.env.Environment接口来处理环境变量。可以通过在Spring Bean中注入Environment来访问环境变量。

    • 可以使用getProperty(String key)方法获取指定键的环境变量值,其中key是环境变量的键。

    • 例如,假设有一个环境变量MY_VAR=value,可以使用以下方式在Spring Bean中获取该环境变量的值:

      @Autowired
      private Environment environment;
      
      public void someMethod() {
          String myVarValue = environment.getProperty("MY_VAR");
          // 使用myVarValue进行后续处理
      }
      
  3. Spring Boot自带的配置文件(application.propertiesapplication.yml):

    • Spring Boot使用org.springframework.boot.context.properties.ConfigurationProperties注解来绑定配置文件中的属性到Java对象上。可以通过在Spring Bean上使用@ConfigurationProperties注解来实现属性绑定。

    • 配置文件中的属性会自动与带有相同名称的Java对象的属性进行绑定。

    • 例如,假设有一个配置文件中的属性server.port=8080,可以使用以下方式在Spring Bean中绑定该属性:

      @Component
      @ConfigurationProperties(prefix = "server")
      public class ServerProperties {
          private int port;
      
          public int getPort() {
              return port;
          }
      
          public void setPort(int port) {
              this.port = port;
          }
      }
      

      在上述示例中,server.port属性会自动绑定到ServerProperties对象的port属性上。可以通过注入ServerProperties Bean 来访问该属性的值。

通过上述方式,Spring Boot能够自动识别并解析来自命令行参数、环境变量和配置文件的配置参数,使开发者可以方便地使用这些配置参数来配置应用程序的行为。

了解了三种不同来源的参数是如何被解析的,感兴趣的可以读一下源码,观察一下他们是如何解析的,这里我就不分析源码了。

4. springboot里面集成的第三方组件,他们的配置参数如何被管理的?

现在,很多开源组件库都基本集成到springboot里了,也就是按照springboot的starter规范做了一些自动化配置,并抽离出自身的一些配合参数到application.properties里面。

有一些组件有他们特有的配置,可能是考虑到配置在application.properties配置文件里面显的太过于冗长,不容易维护,所以需要独立出一个单独的配置文件来管理。

比如mybatis,log4j2等等这些组件。

mybatis的独立配置文件:

mybatis有一个设置文件,一般都是叫做,xxx-config.xml,内容基本如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 设置全局属性 -->
    <settings>
        <!-- 开启驼峰命名自动映射 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 其他配置项 -->
    </settings>

    <!-- 配置插件 -->
    <plugins>
        <!-- 自定义插件1 -->
        <plugin interceptor="com.example.MyPlugin1">
            <!-- 自定义插件1的配置项 -->
        </plugin>
        
        <!-- 自定义插件2 -->
        <plugin interceptor="com.example.MyPlugin2">
            <!-- 自定义插件2的配置项 -->
        </plugin>
        
        <!-- 其他插件 -->
    </plugins>

    <!-- 加载映射文件 -->
    <mappers>
        <!-- 单个映射文件的配置 -->
        <mapper resource="com/example/mapper/SomeMapper.xml"/>

        <!-- 批量加载映射文件的配置 -->
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

这是一个简单的示例,展示了 MyBatis 的配置文件结构。你可以根据自己的需求进行配置。其中包含了以下几个重要的元素和属性:

  1. <settings>:用于配置全局属性和设置,例如开启驼峰命名自动映射。
  2. <plugins>: 中配置自定义插件。每个插件都使用 标签表示,其中的 interceptor 属性指定了插件的实现类的完全限定名。
  3. <mappers>:用于加载映射文件的配置,可以单个配置或者批量配置。
    • <mapper resource="com/example/mapper/SomeMapper.xml"/>:指定单个映射文件的路径。
    • <package name="com.example.mapper"/>:指定一个包名,MyBatis 会自动扫描该包下的映射文件。

log4j2的独立配置文件

以下是一个Log4j2 配置文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <Property name="logDir">logs</Property>
    </Properties>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>

        <RollingFile name="File" fileName="${logDir}/application.log"
                     filePattern="${logDir}/application-%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
            <DefaultRolloverStrategy max="10" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="File" />
        </Root>

        <Logger name="com.example" level="debug" additivity="false">
            <AppenderRef ref="File" />
        </Logger>
    </Loggers>
</Configuration>

在这个示例中,添加了一些新的配置选项,你可以根据实际需求,调整日志级别、输出格式、文件路径等配置项:

  • <Properties>:在此部分可以定义属性,供后面引用。示例中定义了 logDir 属性,用于指定日志文件目录。
  • monitorInterval:配置文件的监视间隔,单位为秒。如果监视间隔内的配置文件更改,Log4j2 将重新配置自己。在示例中设置为 30 秒。
  • RollingFile Appender:使用滚动文件策略,可以按时间滚动日志文件。示例中的文件名为 application.log,并使用 %d{yyyy-MM-dd} 进行日期格式化。
  • <Policies>:用于配置日志文件滚动策略,示例中使用 TimeBasedTriggeringPolicy,每天滚动一次日志文件。
  • <DefaultRolloverStrategy>:配置日志文件滚动的策略,默认为最多保留 10 个日志文件。

以上尽管这些组件都有独立配置文件,但是,这些独立配置文件依然和springboot的application.properties有关联。

比如mybatis,在application.properties指定独立配置的加载路径:

mybatis-plus.config-location=classpath:xxx-config.xml

比如log4j2:

logging.config=classpath:log.xml

所以,如果我们在开发一个组件集成到springboot里面的时候,尽可能的遵循它的规范,用application.properties来管理你的配置,如果你的配置比较多且比较杂,比如像mybatis,log4j2这样的组件,有自己独立的配置,尽量将这些独立配置文件也和application.properties建立着关联。

以上,我一直在强调要和application.properties建立关联是因为,后期我们的项目比如进行容器化部署,这些配置那面要修改,那就方便多了。

具体可以参照我的这篇文章 : Docker和Kubernetes部署Spring Boot项目:如何灵活修改配置文件?

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-07 20:19
真是乐了:模版不太好 而且字太密了项目说的太细碎
点赞 评论 收藏
分享
无情咸鱼王的秋招日记之薛定谔的Offer:好拒信,偷了,希望有机会用到
点赞 评论 收藏
分享
牛客963010790号:为什么还要收藏
点赞 评论 收藏
分享
11-05 17:51
南昌大学 Java
在做ppt的袋鼠很完美:隔了三星期被放进人才库的我
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务