如何获取命令行的配置

在 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 工程中获取命令行属性的全场景方案,可根据实际需求(如启动时处理、运行时注入、复杂属性绑定)选择对应方式。

相关推荐
努力努力再努力wz9 小时前
【Linux网络系列】:JSON+HTTP,用C++手搓一个web计算器服务器!
java·linux·运维·服务器·c语言·数据结构·c++
魂梦翩跹如雨9 小时前
死磕排序算法:手撕快速排序的四种姿势(Hoare、挖坑、前后指针 + 非递归)
java·数据结构·算法
带刺的坐椅16 小时前
Solon AI Skills 会是 Agent 的未来吗?
java·agent·langchain4j·solon-ai
jacGJ16 小时前
记录学习--文件读写
java·前端·学习
哈哈不让取名字17 小时前
基于C++的爬虫框架
开发语言·c++·算法
花间相见17 小时前
【JAVA开发】—— Nginx服务器
java·开发语言·nginx
扶苏-su17 小时前
Java---Properties 类
java·开发语言
cypking17 小时前
四、CRUD操作指南
java
2301_7806698618 小时前
文件字节流输出、文件复制、关闭流的方法
java
一条咸鱼_SaltyFish18 小时前
远程鉴权中心设计:HTTP 与 gRPC 的技术决策与实践
开发语言·网络·网络协议·程序人生·http·开源软件·个人开发