【Springboot】命令行参数

什么是命令行参数

从springboot官网可以知道,通过下面三种方式把一些值当作属性放到spring的上下文中,然后可以再代码中直接读取这些属性的值:

  1. 通过环境变量方式environment variable:
    $ SPRING_APPLICATION_JSON=’{“acme”:{“name”:“test”}}’ java -jar myapp.jar
  2. 通过系统属性system property:
    $ java -Dspring.application.json=’{“acme”:{“name”:“test”}}’ -jar myapp.jar
  3. 通过命令行参数command line argument:
    $ java -jar myapp.jar --spring.application.json=’{“acme”:{“name”:“test”}}’

我们今天要讲的就是第三种情况,命令行参数。
首先来说一下什么是命令行参数?
从代码上来讲,命令行参数就是springboot启动类里面那个main方法中的那个args参数,程序启动时传给那个args变量的东东就是命令行参数。

怎么传

那么通过什么方式可以传给他呢?这里介绍两个方式
方式一:通过命令行,如下:

java -jar myproject-0.0.1-SNAPSHOT.jar --debug --Mygroup=a,b --filePath=c:/data/1.txt -myargs=2 testNoArg debug=true

方式二:开发是通过idea直接配置,如下:
在这里插入图片描述
通过上面两种方式后,–debug --Mygroup=a,b --filePath=c:/data/1.txt -myargs=2 testNoArg debug=true 这部分就会当作参数传给我们springboot启动类的main方法中的args参数了(切记:每项后面加空格)。

有什么用

那么启动程序时设置这个参数有什么用呢?我们结合run方法的代码来说明。
1.通过这些启动时设置参数,可以在启动时向Property中添加属性值。一般我们都是通过application.properties来设置Property的值,然后在程序中可以通过@Value注解来使用。但是如果有些值想在启动时设置,然后通过@Value来获取,那么就可以通过启动参数来设置。所有的这些property都放在springboot官网中说的environment(代码里也是)。springboot启动时关于所有的property还有environment相关的设置,都在SpringApplication这个类的run方法中,源码部分如下:

public ConfigurableApplicationContext run(String... args) {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);1】
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments)2;
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		refreshContext(context);3afterRefresh(context, applicationArguments);
		callRunners(context, applicationArguments);
		return context;
	}

【1】中便会把传入的参数进行封装,封装的过程可参考下面的【参数封装过程】。然后得到一个applicationArguments ,这里面就是我们的参数,然后【2】处便把参数的内容放到environment中了,然后environment会放到context中【3】。然后才可以通过@Value获取到了。包括application.properties这些文件中内容都是放到environment中。截了一个向environment中放参数的图,如下
在这里插入图片描述
如果不想这些参数放到environment中,使用下面的代码禁用:

SpringApplication.setAddCommandLineProperties(false)

2.通过将参数封装到ApplicationArguments 后,当我们在代码中可以直接通过注入的方式获取到我们传入给main方法的参数。例子如下:

@Component
public class MyBean {
  @Autowired
  public MyBean(ApplicationArguments args) {
    // --Mygroup=a,b --filePath=c:/data/1.txt -myargs=2 testNoArg TestNoarg2=3
    boolean debug = args.containsOption("debug");
    List<String> files = args.getNonOptionArgs(); //option和nonOption的意思文章下面的【参数封装过程】有介绍
    Set<String> optionNames = args.getOptionNames();
    for (String optionName : optionNames) {
      System.out.println("这是传过来的参数[{}]"+optionName);
    }
    String[] sourceArgs = args.getSourceArgs();
    for (String sourceArg : sourceArgs) {
      System.out.println("这是传过来sourceArgs[{}]"+ sourceArg);
    }
  }
}

参数封装过程

参数封装的代码层次关系大体如下:
SpringApplication.run(ApplicationRunner.class, args)
 |-- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  |-- this.source = new Source(args);
    |-- super(args);【1】
     |-- super(new SimpleCommandLineArgsParser().parse(args));【2】

CommandLineArgs是一个接口,默认实现类DefaultApplicationArguments。

【1】处调用的是Source的父类SimpleCommandLinePropertySource的构造方法,如下:

【1】处调用父类的构造方法如下:
	public SimpleCommandLinePropertySource(String... args) {
		super(new SimpleCommandLineArgsParser().parse(args));
	}

这个构造方法的的参数是一个可变的String类型,所以可以直接把main方法中的参数所有内容都接受到。然后解析这个这些参数内容。解析代码如下:
以参数 --debug --Mygroup=a,b --filePath=c:/data/1.txt -myargs=2 testNoArg TestNoarg2=3 --debug=true 为例子:

class SimpleCommandLineArgsParser {
	public CommandLineArgs parse(String... args) {
		CommandLineArgs commandLineArgs = new CommandLineArgs();
		for (String arg : args) {
		   // 如果-- 开头参数如--filePath=c:/data/1.txt
			if (arg.startsWith("--")) {
				String optionText = arg.substring(2);// 去掉--
				String optionName;
				String optionValue = null;
				//获取参数=后面的内容,如--filePath=c:/data/1.txt最后得到的就是c:/data/1.txt
				int indexOfEqualsSign = optionText.indexOf('=');
				if (indexOfEqualsSign > -1) {// 如果有=号如--filePath=c:/data/1.txt
					optionName = optionText.substring(0, indexOfEqualsSign);//获取=左边的值(filePath)
					optionValue = optionText.substring(indexOfEqualsSign + 1);//获取=右边的值(c:/data/1.txt)
				}
				else {// 没有=号就直接赋值,如例子中的--debug,就直接将debug赋值
					optionName = optionText;
				}
				commandLineArgs.addOptionArg(optionName, optionValue);// 【3】
			}
			else {
				commandLineArgs.addNonOptionArg(arg);// 【4】 不是--开头的参数,直接添加
			}
		}
		return commandLineArgs;
	}
}

从上面这段代码【3】【4】可以看出,传入的参数可以分为两类:option和NonOption【这两个概念很重要】。
以两个 – 开头的参数(比如- - debug)为option,其他的都为NonOption

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值