Spring Boot命令行启动添加参数

简介: Spring Boot命令行启动添加参数

一、Spring Boot命令行三种参数形式

通过java -jar启动springboot的jar项目时,可以动态传递参数来进行配置和开发,比如

java -jar xxx.jar --server.port=8081

可以通过server.port修改项目启动的端口,通过命令行传递的参数具有更高的优先级,会覆盖同名的其他配置参数。

启动Spring Boot项目时传递参数,有三种参数形式:

1、选项参数

选项参数,上面的示例便是选项参数的使用方法,通过“–-server.port”来设置应用程序的端口。基本格式为“--name=value”(“--”为连续两个减号)。其配置作用等价于在application.properties中配置的server.port=8081。

2、非选项参数

java -jar xxx.jar abc def

上述示例中,“abc”和“def”便是非选项参数。

3、系统参数

系统参数,该参数会被设置到系统变量中,使用示例如下

java -jar -Dserver.port=8081 xxx.jar

二、参数值得获取

选项参数和非选项参数均可以通过ApplicationArguments接口获取,具体获取方法直接在使用参数的类中注入该接口即可,比如这里通过命令行参数获取数据库连接信息创建数据源

@Component
public class ComponentDB {
 
    @Autowired
    private ApplicationArguments applicationArguments;
 
    public final  String driverClassName = "com.mysql.cj.jdbc.Driver";
    //private final  String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true";
 
    @Bean
    DataSource dataSource(){
        System.out.println("# 非选项参数数量: " + applicationArguments.getNonOptionArgs().size());
        System.out.println("# 选项参数数量: " + applicationArguments.getOptionNames().size());
        
        System.out.println("# 非选项参具参数:");
        applicationArguments.getNonOptionArgs().forEach(System.out::println);
        System.out.println("# 选项参数具体参数:");
        applicationArguments.getOptionNames().forEach(optionName ->{
            System.out.println("--" + optionName + "=" + applicationArguments.getOptionValues(optionName));
        });
 
        System.out.println("**************************");
 
        String dbUrl = applicationArguments.getOptionValues("url").get(0);
        String url = "jdbc:mysql://"+dbUrl+"?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true";
        String name = applicationArguments.getOptionValues("name").get(0);
        String pass = applicationArguments.getOptionValues("pass").get(0);
        return DataSourceBuilder.create()
                .url(url)
                .username(name)
                .password(pass)
                .driverClassName(driverClassName).build();
    }
}

启动

java -jar springboottest-0.0.1-SNAPSHOT.jar --url=localhost:3306/test --name=root --pass=root aaa bbb

结果

选项参数,也可以直接通过@Value在类中获取,如下

@RestController
public class TestController {
    @Value("${server.port}")
    private String serverPort;
}

系统参数可以通过java.lang.System提供的方法获取:

String systemServerPort = System.getProperty("server.port");

注意

  • 通过@Value形式可以获得系统参数和选项参数,但通过System.getProperty方法只能获得系统参数
  • 通过@Value形式可以获得系统参数和选项参数,但通过System.getProperty方法只能获得系统参数
  • 使用选项参数时,参数在命令中是位于xxx.jar之后传递的,而系统参数是紧随java -jar之后。

三、ApplicationArguments源码

ApplicationArguments接口中封装了启动时原始参数的数组、选项参数的列表、非选项参数的列表以及选项参数获得和检验。相关源码如下:

public interface ApplicationArguments {  
 
/**  * 原始参数数组(未经过处理的参数)  */  
String[] getSourceArgs();  
 
/**  * 选项参数名称  */  
Set<String> getOptionNames(); 
 
/**  * 根据名称校验是否包含选项参数  */  
boolean containsOption(String name);  
 
/**  * 根据名称获得选项参数  */  
List<String> getOptionValues(String name);  
  
/**  * 获取非选项参数列表  */  
List<String> getNonOptionArgs();
}
 

上面直接使用了ApplicationArguments的注入和方法,那么它的对象是何时被创建,何时被注入Spring容器的?

在执行SpringApplication的run方法的过程中会获得传入的参数,并封装为ApplicationArguments对象。相关源代码如下:

public ConfigurableApplicationContext run(String... args) { 
 try {    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);    // ...    prepareContext(context, environment, listeners, // ...  } catch (Throwable ex) {    // ...  }  return context;}

在上述代码中,通过创建一个它的实现类DefaultApplicationArguments来完成命令行参数的解析。

DefaultApplicationArguments部分代码如下:

public class DefaultApplicationArguments implements ApplicationArguments {
    private final Source source;
    private final String[] args;
 
    public DefaultApplicationArguments(String... args) {
        Assert.notNull(args, "Args must not be null");
        this.source = new Source(args);
        this.args = args;
    }
 
    public String[] getSourceArgs() {
        return this.args;
    }
 
    public Set<String> getOptionNames() {
        String[] names = this.source.getPropertyNames();
        return Collections.unmodifiableSet(new HashSet(Arrays.asList(names)));
    }
 
    public boolean containsOption(String name) {
        return this.source.containsProperty(name);
    }
 
    public List<String> getOptionValues(String name) {
        List<String> values = this.source.getOptionValues(name);
        return values != null ? Collections.unmodifiableList(values) : null;
    }
 
    public List<String> getNonOptionArgs() {
        return this.source.getNonOptionArgs();
    }
 
    private static class Source extends SimpleCommandLinePropertySource {
        Source(String[] args) {
            super(args);
        }
 
        public List<String> getNonOptionArgs() {
            return super.getNonOptionArgs();
        }
 
        public List<String> getOptionValues(String name) {
            return super.getOptionValues(name);
        }
    }
}

通过构造方法,将args赋值给成员变量args,其中接口ApplicationArguments中getSourceArgs方法的实现在该类中便是返回args值。

针对成员变量Source(内部类)的设置,在创建Source对象时调用了其父类SimpleCommandLinePropertySource的构造方法,

public SimpleCommandLinePropertySource(String... args) {
    super(new SimpleCommandLineArgsParser().parse(args));
  }

在该方法中创建了真正的解析器SimpleCommandLineArgsParser并调用其parse方法对参数进行解析。

public CommandLineArgs parse(String... args) {
    CommandLineArgs commandLineArgs = new CommandLineArgs();
    for (String arg : args) {
      if (arg.startsWith("--")) {
        String optionText = arg.substring(2);
        String optionName;
        String optionValue = null;
        int indexOfEqualsSign = optionText.indexOf('=');
        if (indexOfEqualsSign > -1) {
          optionName = optionText.substring(0, indexOfEqualsSign);
          optionValue = optionText.substring(indexOfEqualsSign + 1);
        }
        else {
          optionName = optionText;
        }
        if (optionName.isEmpty()) {
          throw new IllegalArgumentException("Invalid argument syntax: " + arg);
        }
        commandLineArgs.addOptionArg(optionName, optionValue);
      }
      else {
        commandLineArgs.addNonOptionArg(arg);
      }
    }
    return commandLineArgs;
  }

上述解析规则比较简单,就是根据“--”和“=”来区分和解析不同的参数类型。

通过上面的方法创建了ApplicationArguments的实现类的对象,但此刻还并未注入Spring容器,注入Spring容器是依旧是通过上述SpringApplication#run方法中调用的prepareContext方法来完成的。相关代码如下:

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) 
{  // ...  
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();  
// 通过beanFactory将ApplicationArguments的对象注入Spring容器  beanFactory.registerSingleton("springApplicationArguments", applicationArguments);  
// ...}

以上就是关于Spring Boot中ApplicationArguments的相关源码解析


相关文章
|
9月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
|
Java Spring
SpringBoot 实战 不同参数调用不同实现
本文介绍了如何在实际工作中根据不同的入参调用不同的实现,采用`map+enum`的方式实现优雅且严谨的解决方案。通过Spring Boot框架中的工厂模式或策略模式,避免了使用冗长的`if...else...`语句。文中详细展示了定义接口、实现类、枚举类以及控制器调用的代码示例,确保用户输入的合法性并简化了代码逻辑。
541 1
SpringBoot 实战 不同参数调用不同实现
|
JSON 前端开发 Java
Spring MVC——获取参数和响应
本文介绍了如何在Spring框架中通过不同的注解和方法获取URL参数、上传文件、处理cookie和session、以及响应不同类型的数据。具体内容包括使用`@PathVariable`获取URL中的参数,使用`MultipartFile`上传文件,通过`HttpServletRequest`和`@CookieValue`获取cookie,通过`HttpSession`和`@SessionAttribute`获取session,以及如何返回静态页面、HTML代码片段、JSON数据,并设置HTTP状态码和响应头。
325 1
Spring MVC——获取参数和响应
|
缓存 前端开发 Java
springboot 的单体服务 字典参数转译
本文介绍了如何在Spring Boot项目中使用缓存来管理字典参数,并确保前后端数据一致性。首先,通过`@EnableCaching`启用缓存功能,接着创建一个自定义的字典缓存类`DicCache`。然后,通过配置类将`DicCache`添加到`cacheManager`中。此外,对字典服务进行改造,使用`@CachePut`和`@CacheEvict`注解保证数据一致性。最后,实现自定义注解`@DicSerializer`和序列化处理类`DictSerializerHandel`,用于在序列化过程中自动转换字典值。通过这种方式,可最小化代码改动并提高系统性能。
537 6
springboot 的单体服务 字典参数转译
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
198 2
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
486 2
|
JSON Java 数据格式
springboot 参数统一处理
springboot 参数统一处理
246 2
|
监控 Java Maven
springboot学习二:springboot 初创建 web 项目、修改banner、热部署插件、切换运行环境、springboot参数配置,打包项目并测试成功
这篇文章介绍了如何快速创建Spring Boot项目,包括项目的初始化、结构、打包部署、修改启动Banner、热部署、环境切换和参数配置等基础操作。
2088 0
|
Java Spring
spring boot 启动项目参数的设定
spring boot 启动项目参数的设定
472 0

热门文章

最新文章

下一篇
开通oss服务