如何获取命令行的配置

在 Spring Boot 工程中获取命令行属性,核心是利用 Spring 框架对命令行参数的封装(比原生 Java 更便捷),同时兼容 Spring Boot 的配置优先级规则。以下是 不同场景的完整实现方式,涵盖核心需求:

一、核心概念:Spring Boot 中的命令行属性

Spring Boot 会将命令行传入的参数(以 -- 开头)解析为 配置属性 ,并纳入 Spring 的 Environment 体系,优先级高于配置文件(如 application.yml)。

  • 格式:java -jar app.jar --server.port=8081 --custom.name=test
  • -- 开头的普通参数:也可获取(如 java -jar app.jar arg1 arg2)。

二、场景 1:获取 -- 开头的命令行配置属性(最常用)

这是 Spring Boot 推荐的方式,命令行参数会被解析为 Spring 环境属性,可通过以下 3 种方式获取:

方式 1:通过 Environment 直接获取

注入 org.springframework.core.env.Environment,调用 getProperty() 获取属性值:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CmdPropertyController {

    @Autowired
    private Environment environment;

    @GetMapping("/get-cmd-prop")
    public String getCmdProperty() {
        // 获取命令行传入的 --server.port
        String port = environment.getProperty("server.port");
        // 获取自定义命令行属性 --custom.name
        String customName = environment.getProperty("custom.name");
        return "port: " + port + ", customName: " + customName;
    }
}
方式 2:通过 @Value 注解注入

直接将命令行属性注入到变量中,简化代码:

java 复制代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CmdValueController {

    // 注入命令行的 --server.port(无默认值时,未传则报错)
    @Value("${server.port}")
    private String serverPort;

    // 注入自定义属性,设置默认值(未传则用默认值)
    @Value("${custom.name:defaultName}")
    private String customName;

    @GetMapping("/get-cmd-value")
    public String getCmdValue() {
        return "serverPort: " + serverPort + ", customName: " + customName;
    }
}
方式 3:绑定到配置类(推荐复杂属性)

如果有多个自定义命令行属性,可绑定到 @ConfigurationProperties 配置类,更易维护:

java 复制代码
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

// 绑定前缀为 "custom" 的命令行属性
@Component
@ConfigurationProperties(prefix = "custom")
public class CustomCmdProperties {
    private String name;
    private Integer age;

    // 生成 getter/setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

使用时注入配置类:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CmdConfigController {

    @Autowired
    private CustomCmdProperties customCmdProperties;

    @GetMapping("/get-cmd-config")
    public String getCmdConfig() {
        return "customName: " + customCmdProperties.getName() 
                + ", customAge: " + customCmdProperties.getAge();
    }
}

测试命令:java -jar app.jar --custom.name=test --custom.age=20

三、场景 2:获取非 -- 开头的普通命令行参数

如果传入的是普通参数(无 -- 前缀,如 java -jar app.jar arg1 arg2),需通过 Spring Boot 的 ApplicationArguments 获取:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CommonArgsController {

    // 注入 ApplicationArguments,Spring Boot 自动封装命令行参数
    @Autowired
    private ApplicationArguments applicationArguments;

    @GetMapping("/get-common-args")
    public String getCommonArgs() {
        // 获取所有非 -- 开头的普通参数(如 arg1、arg2)
        String[] nonOptionArgs = applicationArguments.getNonOptionArgs().toArray(new String[0]);
        // 获取所有 -- 开头的选项参数名(如 server.port、custom.name)
        String[] optionNames = applicationArguments.getOptionNames().toArray(new String[0]);
        // 获取某个选项参数的值(如 --custom.name=test → [test])
        String customName = applicationArguments.getOptionValues("custom.name").get(0);

        return "普通参数:" + String.join(",", nonOptionArgs) 
                + ",选项参数名:" + String.join(",", optionNames)
                + ",custom.name:" + customName;
    }
}

测试命令:java -jar app.jar arg1 arg2 --custom.name=test

输出:普通参数:arg1,arg2,选项参数名:custom.name,custom.name:test

四、场景 3:启动类中直接获取命令行参数

如果需要在 Spring Boot 启动阶段(上下文初始化前)获取命令行参数,可在 main 方法中处理:

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CmdDemoApplication {

    public static void main(String[] args) {
        // 1. 原生 Java 方式:直接遍历 main 方法的 args 数组
        System.out.println("原生命令行参数:");
        for (String arg : args) {
            System.out.println(arg);
        }

        // 2. 启动 Spring 上下文,并传入参数(必须)
        var applicationContext = SpringApplication.run(CmdDemoApplication.class, args);

        // 3. 启动后从上下文获取 Environment,解析 -- 开头的属性
        var environment = applicationContext.getEnvironment();
        String port = environment.getProperty("server.port");
        System.out.println("启动后获取 server.port:" + port);
    }
}

五、关键注意事项

  1. 配置优先级 :命令行属性(--xxx)优先级最高,会覆盖 application.yml、环境变量等配置;

  2. 参数格式

    • 选项参数必须以 -- 开头(如 --key=value--key value);
    • 多个值的参数:--custom.list=1 --custom.list=2,可通过 applicationArguments.getOptionValues("custom.list") 获取列表;
  3. 特殊字符处理 :如果参数包含空格/特殊字符,需用引号包裹(如 --custom.desc="hello world");

  4. 禁用命令行参数 :如果不想让命令行参数覆盖配置,可在启动类中设置:

    java 复制代码
    SpringApplication application = new SpringApplication(CmdDemoApplication.class);
    application.setAddCommandLineProperties(false); // 禁用命令行参数解析
    application.run(args);

六、常用工具方法(封装获取)

java 复制代码
import org.springframework.boot.ApplicationArguments;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class CmdPropertyUtil {

    private final Environment environment;
    private final ApplicationArguments applicationArguments;

    // 构造器注入
    public CmdPropertyUtil(Environment environment, ApplicationArguments applicationArguments) {
        this.environment = environment;
        this.applicationArguments = applicationArguments;
    }

    // 获取单个命令行配置属性(带默认值)
    public String getCmdProperty(String key, String defaultValue) {
        return environment.getProperty(key, defaultValue);
    }

    // 获取普通命令行参数列表(非 -- 开头)
    public String[] getCommonArgs() {
        return applicationArguments.getNonOptionArgs().toArray(new String[0]);
    }

    // 判断是否包含某个选项参数(如 --debug)
    public boolean hasOption(String optionName) {
        return applicationArguments.containsOption(optionName);
    }
}

以上是 Spring Boot 工程中获取命令行属性的全场景方案,可根据实际需求(如启动时处理、运行时注入、复杂属性绑定)选择对应方式。

相关推荐
Tony Bai6 小时前
高并发后端:坚守 Go,还是拥抱 Rust?
开发语言·后端·golang·rust
wjs20246 小时前
Swift 类型转换
开发语言
没有bug.的程序员6 小时前
服务安全:内部服务如何防止“裸奔”?
java·网络安全·云原生安全·服务安全·零信任架构·微服务安全·内部鉴权
一线大码6 小时前
SpringBoot 3 和 4 的版本新特性和升级要点
java·spring boot·后端
秃了也弱了。7 小时前
python实现定时任务:schedule库、APScheduler库
开发语言·python
weixin_440730507 小时前
java数组整理笔记
java·开发语言·笔记
weixin_425023007 小时前
Spring Boot 实用核心技巧汇总:日期格式化、线程管控、MCP服务、AOP进阶等
java·spring boot·后端
一线大码7 小时前
Java 8-25 各个版本新特性总结
java·后端
Thera7777 小时前
状态机(State Machine)详解:原理、优缺点与 C++ 实战示例
开发语言·c++
2501_906150567 小时前
私有部署问卷系统操作实战记录-DWSurvey
java·运维·服务器·spring·开源