SpringBoot启动命令行参数【-D】和【--】的区别,启动命令和IDEA如何传递:VM参数、命令行参数、系统参数、环境变量参数、main方法参数
【-D】和【--】两种写法都可以在命令行传入参数,实现覆盖 application.properties
中的配置项,不过写法有些不同
【-D】虚拟机参数
以运行jar包为例,写法为:
|
# 参数写法为:-Dproperty=value |
|
java -Dserver.port=1234 -jar app.jar |
【-D】要放到 -jar 前面,否则参数无效
在idea中通过虚拟机选项这里传递:
代码中可以通过系统属性 System.getProperties()
获取
|
public static void main(String[] args) { |
|
SpringApplication.run(App.class, args); |
|
|
|
// 1234 |
|
System.out.println(System.getProperty("server.port")); |
|
|
|
System.out.println("*****启动成功*****"); |
|
} |
【--】命令行参数
从main方法的参数传入,springboot会对这种参数进行自动解析
写法为:
|
java -jar app.jar --server.port=4321 |
【--】参数不能放到前面,否则会报错
在idea中这么传递:
代码中是通过main
函数参数 String[] args
传入
再通过SpringApplication.run(App.class, args)
传入springboot
进行解析的
可以通过实现 EnvironmentAware接口
注入环境对象,可以读取命令行参数
|
|
|
public class App implements EnvironmentAware { |
|
|
|
static Environment environment; |
|
|
|
public static void main(String[] args) { |
|
SpringApplication.run(App.class, args); |
|
|
|
// 1234 |
|
System.out.println(System.getProperty("server.port")); |
|
// 4321 同名的命令行参数覆盖虚拟机参数 |
|
System.out.println(environment.getProperty("server.port")); |
|
|
|
System.out.println(environment.getProperty("user.dir")); |
|
|
|
System.out.println("*****启动成功*****"); |
|
} |
|
// 注入环境对象 |
|
|
|
public void setEnvironment(Environment environment) { |
|
App.environment = environment; |
|
} |
|
} |
命令行参数与虚拟机参数同名的,以命令行参数优先
Title |
Link |
---|---|
所属专栏 |
【方向盘】-IntelliJ IDEA |
源代码 |
https://github.com/yourbatman/FXP-java-ee |
程序员专用网盘公益上线啦,注册送1G超小容量,帮你实践做减法 |
https://wangpan.yourbatman.cn |
Java开发软件包(Mac) |
https://wangpan.yourbatman.cn/s/rEH0 提取码:javakit |
女娲工程 |
http://152.136.106.14:8761 |
版本约定 |
[Mac OS 12.3],[iTerm2 3.4.15(zsh 5.8)],[IntelliJ IDEA 2021.3.3] |
📚前言
传递参数时,再次感受到IDEA产品设计的伟大和人性化。
作为一枚javaer,对“VM参数、命令行参数、系统参数、环境变量参数、main方法参数”这些名词不陌生,但可能也不太熟悉,分不清楚:不知道怎么传?不知道优先级?
本文依旧具有实操性,提升基础技能,最重要的是:提高效率,留出时间陪朋友、陪家人、陪妹纸~
本文内容相对较长,如果你对中间分析过程不感兴趣,可直接此图拿走,或拉到文末看结论即可。
✍正文
Java应用最终被打为可执行的Jar包(war包不讨论)方可运行,此时能向应用传入参数的唯一方式是:命令行。为了尝试为你彻底讲解清楚,本文采用逐层递进的方式:
- 列出命令行里所有的传参方式
- 用示例代码演示不同传参方式的效果、优先级
- 使用IDEA模拟不同的传参方式
- 因为在开发过程中,我们不可能打出jar包后再调试,那样效率太低,而是将这一切都在IDE里完成
main方法是应用程序的入口,正好Spring Boot的入口就是main方法,而且它作为现代Java应用的基座,现今绝大部分应用都构建在它之上,因此本文基于Spring Boot应用进行讲解,更具有现实意义。
🌈准备工作
准备工作主要分为三部分:
- 构建示例代码
- 命令行里所有传参方式
- IDEA模拟传参功能
🚀构建示例代码
为了让参数的效果更直观,笔者特意花了“很长时间”构建出代码示例,对本代码做出说明:
- 以Spring Boot作为底座,构建在其之上
- 只关注两个key的值:
yourbatman.name
和yourbatman.age
- 由于自带的属性k-v众多,全打印输出将无法查看和对比,因此做了聚焦
- 只关注三大属性源:系统属性(sysProp)、环境属性(sysEnv)、命令行属性(cli)
@SpringBootApplication
public class Application {
private static final String NAME = "name";
private static final String AGE = "age";
public static void main(String[] args) {
System.out.println("main方法的参数\t" + Arrays.toString(args));
Runtime runtime = Runtime.getRuntime();
System.out.println("堆内存能达到的最大值(Xmx可控制它)\t" + ofBytes(runtime.maxMemory()).toMegabytes() + "mb");
System.out.println("堆内存当前获得的大小(Xms可控制它)\t" + ofBytes(runtime.totalMemory()).toMegabytes() + "mb");
System.out.println("堆内存当前剩余大小\t" + ofBytes(runtime.freeMemory()).toMegabytes() + "mb");
System.out.println("==========下面参数来自Java原生==========");
Properties sysProp = System.getProperties();
printFromJava("sysProp", sysProp);
Map<String, String> sysEnv = System.getenv();
printFromJava("sysEnv", sysEnv);
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
ConfigurableEnvironment environment = context.getEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
System.out.println("==========下面参数来自Spring属性源==========");
System.out.println("激活的profile spring.profiles.active对应的值\t" + environment.getProperty("spring.profiles.active"));
System.out.println("激活的profile\t" + Arrays.toString(environment.getActiveProfiles()));
PropertySource<?> cliSource = propertySources.get(COMMAND_LINE_PROPERTY_SOURCE_NAME);
printFromSpring("cli命令行", cliSource);
PropertySource<?> sysEnvSource = propertySources.get(SYSTEM_ENVIRONMENT_BEAN_NAME);
printFromSpring("sysEnv", sysEnvSource);
PropertySource<?> sysPropSource = propertySources.get(SYSTEM_PROPERTIES_BEAN_NAME);
printFromSpring("sysProp", sysPropSource);
System.out.println("========================================");
System.out.println(format("Spring属性源【最终】结果\tname:%s age:%s", environment.getProperty(NAME), environment.getProperty(AGE)));
}
private static void printFromJava(String mark, Map<?, ?> source) {
System.out.println(format("Java原生【" + mark + "】结果\tname:%s age:%s", source.get(NAME), source.get(AGE)));
}
private static void printFromSpring(String mark, PropertySource<?> source) {
if (source == null) {
System.out.println(format("Spring属性源【" + mark + "】结果\tname:%s age:%s", null, null));
} else {
System.out.println(format("Spring属性源【" + mark + "】结果\tname:%s age:%s", source.getProperty(NAME), source.getProperty(AGE)));
}
}
}
当什么都不配置,运行示例代码,输出:
🚀命令行里所有传参方式
命令行:一般指命令提示符,是在操作系统中,提示进行命令输入的一种工作提示符,也叫DOS操作方式。英文:Command Line,简称CLI
。下图是Mac的命令行:
命令行参数,顾名思义:在命令行里的参数,CLI parameter或者CLI argument。
为了解Java命令行能传递哪些参数,笔者特地翻阅了Oracle官方文档,做了简单总结。然后找了一个命令行启动参数示例,可以对照着看:
还有一个也可参考:
nohup java -jar ./$appName -Xmx2g -Xms2g -Xss1m -XX:MaxDirectMemorySize=4G -XX:+UseG1GC
-XX:MaxGCPauseMillis=200 -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDateStamps
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError
-XX:+DisableExplicitGC -XX:-OmitStackTraceInFastThrow -XX:+PrintCommandLineFlags -XX:+UnlockCommercialFeatures -XX:+FlightRecorder
-Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 --apollo.meta=http://10.7.xxx.xxx:8888 > ./server.out 2>&1 &
Java命行令支持一些选项,大的方面可以分为以下几类:
- 标准选项:最常用的,所有JVM的实现都支持。如
- -help
- -version
- -verbose:gc 显示每个垃圾收集(GC)事件的信息
- -javaagent:jarpath[=options] 加载java程序的agent
- -jar filename 执行一个jar应用
- -ea 启用断言。默认情况下,断言在所有的包和类中被禁用
-Dproperty=value
设置一个系统属性值(sysProp)。property是一个没有空格的字符串,value是一个字符串,如果value带有空格那么用引号将其括起来(如-Dfoo=“foo bar”)。这个使用得特别多~
- 非标准选项:针对Java HotSpot虚拟机的通用选项,这类参数不是所有参数所有虚拟机都支持。如
- -X 显示所有可用的-X选项的帮助
- -Xnoclassgc 禁用类的垃圾收集(GC)。这可以节省一些GC时间,从而缩短应用程序运行时的中断时间。注意:这里指的类的回收,而非对象的回收。一般情况下不建议开启此选项
- -Xbootclasspath:path 由分号;分隔的目录、JAR 文件和 ZIP 档案的列表,以搜索引导类文件。这些文件将代替JDK中包含的引导类文件
- -Xloggc:filename 用于记录GC事件信息的文件,并将其重定向到该文件。写入该文件的信息类似于-verbose:gc的输出,一般情况下配置这个而非-verbose:gc
- -Xmssize 可简写为
-Xms
,堆内存最小大小,如-Xms256m。可配合-XX:InitalHeapSize - -Xmxsize 可简写为
-Xmx
,堆内存最大大小,如-Xmx1G。它的效果等同于-XX:MaxHeapSize - -Xmnsize 可简写为
-Xmn
,堆内新生代的大小,如-Xmn256m。可配合-XX:NewSize和-XX:MaxNewSize- 堆内老生代大小就是-Xmx减去-Xmn
- -Xsssize 可简写为
-Xss
,每个线程可使用的内存大小,如-Xss1m。它的效果等同于-XX:ThreadStackSize- 在相同物理内存下,减小这个值能生成更多的线程。但线程不宜过多,经验值是最大不要超过5k个线程
- 高级运行时选项:控制JVM运行期行为。如
- -XX:+FlightRecorder
- -XX:MaxDirectMemorySize=size 如-XX:MaxDirectMemorySize=1m
- -XX:ThreadStackSize=size 如-XX:ThreadStackSize=1024k
- -XX:MaxInlineSize=size 如-XX:MaxInlineSize=35
- -XX:+TraceClassLoading 启用类加载时的跟踪。默认情况下,该选项被禁用,类不被追踪
- 高级JIT编译器选项:控制由Java HotSpot VM执行的动态即时编译(JIT)。
- -XX:CICompilerCount=threads 用于编译的编译器线程数。如-XX:CICompilerCount=2
- -XX:+Inline 启用方法内联。这个选项默认是启用的以提高性能。要禁用方法内联,设置为-XX:-Inline
- -XX:MaxInlineSize=size 设置要被内联的方法的最大字节码大小。如-XX:MaxInlineSize=35m
- 高级可服务性选项:提供了收集系统信息和进行广泛调试的能力。如
- -XX:+HeapDumpOnOutOfMemoryError 当抛出
java.lang.OutOfMemoryError
异常时,通过使用堆分析器(HPROF),启用将Java堆转储到当前目录下的一个文件。配合使用使用-XX:HeapDumpPath选项明确设置堆转储文件路径和名称。默认情况下,该选项被禁用,当抛出OutOfMemoryError异常时,堆不会被转储 - -XX:HeapDumpPath=path 默认情况下,该文件是在当前工作目录下创建的,文件名是java_pidpid.hprof,其中pid是导致错误的进程的标识符,但也可自定义。如
-XX:HeapDumpPath=./java_pid%p.hprof
、-XX:HeapDumpPath=C:/log/java/java_heapdump.log
,当然也可指定目录即可,如-XX:HeapDumpPath=./app/tmp
- -XX:+HeapDumpOnOutOfMemoryError 当抛出
- 高级GC选项:控制Java HotSpot VM如何进行垃圾收集(GC)。如
- -XX:+DisableExplicitGC 禁止处理对System.gc()的调用。该选项默认为禁用,也就是允许System.gc()
- -XX:+UseConcMarkSweepGC 启用旧一代的CMS垃圾收集器。默认情况下,这个选项是禁用的,收集器会根据机器的配置和JVM的类型自动选择
- -XX:MaxMetaspaceSize=size 可以分配给类元数据的最大本地内存量。默认情况下,该大小不受限制。可看情况设置,如-XX:MaxMetaspaceSize=1G
- 代替了Java 8之前的-XX:MaxPermSize
- -XX:MetaspaceSize=size 分配的类元数据空间的大小,首次超过该大小时将触发垃圾收集
- 代替了Java 8之前的-XX:PermSize
- -XX:MaxTenuringThreshold=threshold 转入老生代的存活次数。一般的默认值是15(CMS是6),最大值是15。如果是0,则直接跳过新生代进入老生代
- -XX:SurvivorRatio 新生代中两个survivor和eden的比值。默认值是8,表示两个servivor:eden = 2:8,或者servivor:servivor:eden = 1:1:8
- -XX:NewRatio=ratio 新生代(eden + 2*servivor) 与老年代的比值,默认值是2,表示新生代:老年代 = 1:2
- -XX:+PrintGCDetails 打印每个GC的详细信息。默认情况下,这个选项是禁用的
- -XX:+PrintGCTimeStamps 在每个GC上打印时间戳。默认情况下,这个选项是禁用的
- -
XX:+UseG1GC
启用G1垃圾收集器。G1收集器被推荐给需要大堆(大小约为6GB或更大)且对GC延迟要求有限的应用,推荐显示开启 -XX:G1ReservePercent=percent
堆的百分比(0到50),作为上限保留,以减少G1收集器的推广失败的可能性。默认情况下,这个选项被设置为10%-XX:MaxGCPauseMillis=time
目前暂停时间(以ms为单位)。JVM将尽最大努力来实现它。默认情况下,没有最大暂停时间的值-XX:ParallelGCThreads=threads
年轻代和老年代中用于并行GC线程数。默认值取决于JVM可用的CPU的数量-XX:ConcGCThreads=threads
设置用于并发GC的线程数。默认值取决于JVM可用的CPU的数量- ConcGCThreads = (ParallelGCThreads + 3)/4,这两个参数是JVM调优的重要手段之一
-XX:G1HeapRegionSize=size
堆被细分的区域的大小(1MB~32MB,且必须是2的N次幂),默认根据堆大小来确定(共被分为2048个region)
更多的命令行参数可参见权威Oracle官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
总结一下,命令行里启用java应用可以传参的方式:
- 以
-X
打头 - 以
-XX
打头 - 以
-D
打头的k-v
除此之外,还有两种传参方式也经常看到,统称为程序参数(由程序自己负责解析):
- 以
--
打头 Spring Boot提供支持和解析的传参方式 - 没有打头,直接k-v Spring Boot提供支持和解析的传参方式
下面用一条的启动命令行,完成描述这几种参数方式:
java -Xms1G -Xmx1G -Dname=YourBatman_D -jar application.jar --spring.profiles.active=prod --name="YourBatman_--" age=18
运行示例程序,输出:
main方法的参数 [--spring.profiles.active=prod, --name=YourBatman_--, age=18]
堆内存能达到的最大值(Xmx可控制它) 981mb
堆内存当前获得的大小(Xms可控制它) 981mb
堆内存当前剩余大小 966mb
==========下面参数来自Java原生==========
Java原生【sysProp】结果 name:YourBatman_D age:null
Java原生【sysEnv】结果 name:null age:null
==========下面参数来自Spring属性源==========
激活的profile spring.profiles.active对应的值 prod
激活的profile [prod]
Spring属性源【cli命令行】结果 name:YourBatman_-- age:null
Spring属性源【sysEnv】结果 name:null age:null
Spring属性源【sysProp】结果 name:YourBatman_D age:null
========================================
Spring属性源【最终】结果 name:YourBatman_-- age:null
笔者在图上,标出了对应关系,以辅助你理解:
①和②这两种方式比较特殊,有些是单值方式(+表示开启,-表示禁用),有些是k-v方式。它们有个共同点:只接受指定的参数值,否则就启动报错,如下图所示:
指定的值有哪些?不同的JVM参照各自的官方文档介绍
可以看到,JVM并不认识-Xyourbatman.xxx
这种key,因此启动不了。但值得注意的是,正常启动情况下,-X和-XX值是不会存在系统、环境属性里的,任何属性源里都没有。
①②③是“标准的”JVM参数,因此我们统称为VM Options,由JVM负责解析,时机非常靠前,配置错误影响JVM的启动。④和⑤属于程序参数,由引用负责解析,它们必须在JVM启动后才行,所以必须配置在 -jar xxx.jar的后面,这点一定要注意喽。否则启动不了:
程序参数是传递给了main方法的入参,应用程序再通过解析此入参而获得对应的值的。
🚀IDEA模拟传参功能
java启动Spring Boot应用的命令行共支持5种方式传参,在如此强大的IEDA面前,都是可以模拟的,熟练使用可大大提高开发、调试效率。
用于模拟传参的窗口,长这样:
Tips:若你的IDEA版本比较低的话,窗口长得不尽相同,但功能区大同小异
在这个窗口里,咋一看能传递参数的仅有VM options
这一个地方可供我们输入。难道它一个承担了所有?
🚩在VM options区域传参
在VM options
区域(也叫CLI arguments命令行参数)填入下面参数试一下:
-Xms1G -Xmx1G -Dname=YourBatman_D
运行示例代码,输出:
main方法的参数 []
堆内存能达到的最大值(Xmx可控制它) 981mb
堆内存当前获得的大小(Xms可控制它) 981mb
堆内存当前剩余大小 955mb
==========下面参数来自Java原生==========
Java原生【sysProp】结果 name:YourBatman_D age:null
Java原生【sysEnv】结果 name:null age:null
==========下面参数来自Spring属性源==========
激活的profile spring.profiles.active对应的值 null
激活的profile []
Spring属性源【cli命令行】结果 name:null age:null
Spring属性源【sysEnv】结果 name:null age:null
Spring属性源【sysProp】结果 name:YourBatman_D age:null
========================================
Spring属性源【最终】结果 name:YourBatman_D age:null
完美。从输出的结果中可以很清楚的看到,-Dkey=value
属性值会进入到系统属性sysProp里和Spring环境中的sysProp属性源里。
①②③可以在这里输,那④⑤呢?上面有提到④⑤必须放在-jar xxx.jar
的后面才行,在IDEA这个输入框里如何体现“后面”?这个时候如果你在VM options
后面直接输入:
--spring.profiles.active=test
得到的必然是大大的报错:
那怎么办,难道IDEA不支持④⑤方式传参?
当然不是,既然④⑤属于程序参数,那就再找找喽。它藏在这里了:
将它勾选上:
🚩在Program arguments区域传参
上图中的Program arguments区域也可叫命令行参数,但更准确的叫法是程序参数:由应用程序负责去解析(而非JVM)。
来吧,在此区域键入值
--name=YourBatman_-- age=18
运行示例代码,输出:
main方法的参数 [--name=YourBatman_--, age=18]
堆内存能达到的最大值(Xmx可控制它) 3641mb
堆内存当前获得的大小(Xms可控制它) 245mb
堆内存当前剩余大小 233mb
==========下面参数来自Java原生==========
Java原生【sysProp】结果 name:null age:null
Java原生【sysEnv】结果 name:null age:null
==========下面参数来自Spring属性源==========
激活的profile spring.profiles.active对应的值 null
激活的profile []
Spring属性源【cli命令行】结果 name:YourBatman_-- age:null
Spring属性源【sysEnv】结果 name:null age:null
Spring属性源【sysProp】结果 name:null age:null
========================================
Spring属性源【最终】结果 name:YourBatman_-- age:null
可以看到,name这对k-v并没有放进Java原生的sysProp或者sysEnv内,而只放在了Spring的命令行属性源(SimpleCommandLinePropertySource
)里头。
另外,除了main方法参数以外,age这对k-v没在“任何地方”出现过。咦,怎么回事?难道就因为前面缺两道杠--
吗?是的,既然是Spring应用程序负责解析,那自然需要遵守其规范嘛,参考类SimpleCommandLineArgsParser
:
这就很好理解为什么结果中输出了name这对k-v,而“忽视”了age这对k-v了。
Tips:age这对k-v其实也进入了Spring的命令行属性源(SimpleCommandLinePropertySource),只不过在non-option区,取值时不会被取出来而已
这么一来就全部清晰了:IDEA的VM Options区域负责模拟①②③传参方式,Program arguments区域模拟④⑤传参方式,齐活。
不知你有没有发现,还有一个sysEnv系统环境变量以及Spring的sysEnv属性源一直未被赋予过值,相信笔者肯定不会只是让它来陪跑的,肯定未完。是的,IDEA有能力对它进行赋值。只需勾选:
视窗新增环境变量传参输入区域:
🚩在Environment variables区域传参
什么叫环境变量?这对于技术人都不陌生,macOS/Linux系统使用echo $变量名
可查看该环境下此变量的值,windows也有对应的查看方式。
应用运行在操作系统内,所以可以读到所有的环境变量。不同的应用获取到的值都是一样的。但很明显,当开发环境下咱程序需要一个环境变量时,若去操作系统层面添加实在太麻烦了,事后还得记得删除并且还无法做到应用间隔离。这时候IDEA就出马解决了这个问题。
在⑥区域写上参数:
name=YourBatman_ENV;age=18_ENV
运行示例代码,输出:
main方法的参数 []
堆内存能达到的最大值(Xmx可控制它) 3641mb
堆内存当前获得的大小(Xms可控制它) 245mb
堆内存当前剩余大小 233mb
==========下面参数来自Java原生==========
Java原生【sysProp】结果 name:null age:null
Java原生【sysEnv】结果 name:YourBatman_ENV age:18_ENV
==========下面参数来自Spring属性源==========
激活的profile spring.profiles.active对应的值 null
激活的profile []
Spring属性源【cli命令行】结果 name:null age:null
Spring属性源【sysEnv】结果 name:YourBatman_ENV age:18_ENV
Spring属性源【sysProp】结果 name:null age:null
========================================
Spring属性源【最终】结果 name:YourBatman_ENV age:18_ENV
可以很清楚的看到,自定义环境变量属性值会进入到系统属性sysEnv里 和 Spring环境中的sysEnv属性源里。
在这里设置的环境变量,有且仅属于这个入口,其它应用or其它入口都获取不到它,真可谓使用方便并且隔离性还非常优秀,真不愧是IDEA。
Tips:命令行方式启动jar包时,无法为应用单独指定环境变量,此功能是IDEA为方便开发而“特制”的
🌈 命令行参数总结
当一个Spring Boot应用被打成jar后,使用命令行启动时,输入参数的方式共有5种,而IDEA共支持6种,它们的对应关系是:
命令行方式 |
IDEA方式 |
---|---|
① -X |
VM Options区域 |
② -XX |
VM Options区域 |
③ -Dkey=value |
VM Options区域 |
④ --key=value |
Program arguments区域 |
⑤ key=value |
Program arguments区域 |
– |
Environment variables区域 |
另外,画了一张图作为总结:
🚀几种传参方式的值优先级
在命令行里传递自定义参数,总的来说有2种方式:
- ③:-Dkey=value方式,去到sysProp和Spring的sysProp属性源
- ④:–key=value方式,只去到Spring的命令行属性源
考虑到还有环境变量,因此这里也带它一起玩。笔者借助IDEA的能力,也往环境变量里放相同的key。
- ⑥:环境变量方式,去到sysEnv和Spring的sysEnv属性源
不同区域,相同key设置的值情况如下:
// ③ -D方式
-Dname=YourBatman_D -Dage=18_D
// ④ --方式
--name=YourBatman_-- --age=18_--
// ⑥ 环境变量
name=YourBatman_ENV;age=18_ENV
在IDEA将值放入对应区域:
运行示例代码,输出:
main方法的参数 [--name=YourBatman_--, --age=18_--]
堆内存能达到的最大值(Xmx可控制它) 3641mb
堆内存当前获得的大小(Xms可控制它) 245mb
堆内存当前剩余大小 233mb
==========下面参数来自Java原生==========
Java原生【sysProp】结果 name:YourBatman_D age:18_D
Java原生【sysEnv】结果 name:YourBatman_ENV age:18_ENV
==========下面参数来自Spring属性源==========
激活的profile spring.profiles.active对应的值 null
激活的profile []
Spring属性源【cli命令行】结果 name:YourBatman_-- age:18_--
Spring属性源【sysEnv】结果 name:YourBatman_ENV age:18_ENV
Spring属性源【sysProp】结果 name:YourBatman_D age:18_D
========================================
Spring属性源【最终】结果 name:YourBatman_-- age:18_--
从“Spring属性源【最终】结果”来看,最终,④程序参数win。
这从Spring属性源顺序上,很好理解这个结果:
④的属性源在“最”上面,优先级最高,所以最终win。
Tips:Spring Boot属性源是一套复杂的体系,是理解Spring Boot配置、配置中心的核心,本文不做展开
🚀概念解释
读完本文后,标题上涉及到的几个概念就很好解释了。
🚩VM参数
特指JVM虚拟机专用的参数,如-Xms -Xmx -XX:MaxMetaspaceSize=size等等,通过方式①②传递进来
🚩命令行参数
它是个统称,毕竟打成jar包后所有参数都只能通过命令行传递。
但是,在Spring Boot应用场景下,命令行参数常常特指commandLineArgs
,也就是通过方式④⑤传递进来
🚩系统参数
系统级别的属性,存储在System.getProperties()和Spring的sysProp属性源里,通过方式③传递进来
🚩环境变量参数
命令行里启动jar包的方式无法为应用专门特定的传入环境变量参数,只能“改全局”的环境变量,所有应用共用。
但在开发场景下,使用IDEA可为应用定制,通过方式⑥传递进来
🚩main方法参数
它也是个统称:在-jar xxx.jar
后面键入的所有参数都会被作为main方法参数传入进来,由应用程序自己负责解析。
Spring利用了这个特点,定了自己的规范--key=value
用来传递参数到commandLineArgs
属性源,优先级比sysProp和sysEnv都高。
🌈 提问
由于本文篇幅已经比较长了,但还有几个方面的知识点我觉得还没表述的,这里使用提问的方式列出来,想研究or实战这块的小伙伴可自己试试。
- 命令行参数、系统参数、环境变量等,他们的key区分大小写吗?
- 站在IDEA产品设计的角度,为何IDEA运行视窗只提供出VM Options区域让你输入?
- IDEA针对Spring应用的运行视窗,有一个
Active profiles
。如果这里写值,通过spring.profiles.active
这个key能取到吗?通过environment.getActiveProfiles()
呢?
🍞总结
通读本文下来,是否觉得终于有人把这些概念给撇清了。如果有,那就是本文的意义所在。
本文内容不难,但希望通过文字、案例来把它讲解得清楚,笔者还是狠下了一番功夫的,期待你的关注,留言交流。
本专栏上下文
- 【方向盘】Spring Boot 2.7.0正式发布,弃用OkHttp 3、弃用spring.factories机制
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(Git&Other&完结篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(Live Template&Postfix Completion篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(重构篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(代码补全篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(运行/调试篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(视窗、选择篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(导航篇)
- 【方向盘】使用IDEA的60+个快捷键分享给你,权为了提效(操作系统、终端篇)
我是方向盘(YourBatman):前25年不会写Hallo World、早已毕业的大龄程序员。高中时期《梦幻西游》骨灰玩家,网瘾失足、清考、延期毕业、房产中介、保险销售、送外卖…是我不可抹灭的黑标签
- 🎓2013.07 清考、毕业答辩3次未通过、延期毕业
- 🏷2013.08-2014.07 宁夏中介公司卖二手房1年,毕业后第1份工作
- ️️🏷2014.07-2015.05 荆州/武汉,泰康人寿卖保险3月、饿了么送外卖2月,还有炸鸡排、直销等第2345份工作
- 🏷2015.08 开始从事Java开发,闯过外包,呆过大厂!擅长抽象思维,任基础架构团队负责人
- 🏷2021.08 因“双减政策”失业!历经9面,终获美团外卖L8的offer
- 🙅🏻♀️Java架构师、Spring开源贡献者、CSDN博客之星年度Top 10、领域建模专家、写作大赛1/2届评委
- 📚高质量代码、规范践行者;DDD领域驱动深度实践;即将出版书籍
《Spring奇淫巧技》
序号 |
专栏名称 |
简介 |
---|---|---|
01 |
【方向盘】-程序人生 |
程序人生,人生程序 |
02 |
【方向盘】-资讯/新特性 |
IDEA、JDK、Spring技术栈…新特性 |
03 |
【方向盘】-IntelliJ IDEA |
熟练使用IDEA就相当拥有物理外挂,助你高效编码 |
04 |
【方向盘】-Bean Validation |
熟练掌握数据校验,减少90%的垃圾代码 |
05 |
【方向盘】-日期时间 |
帮你解决JDK Date、JSR 310日期/其实 的一切问题 |
06 |
【方向盘】-Spring类型转换 |
Spring类型转换-框架设计的基石 |
07 |
【方向盘】-Spring static |
static关键字在Spring里的应用 |
08 |
【方向盘】-Cors跨域 |
关于跨域请求问题,本专栏足矣 |
09 |
【方向盘】-Jackson |
Almost Maybe是最好的Jackson专栏 |
10 |
【方向盘】-Spring配置类 |
专讲@Configuration配置类,你懂的 |
11 |
【方向盘】-Spring技术栈 |
暂无所属小分类的,Spring技术栈大分类 |
12 |
【方向盘】-JDK |
暂无所属小分类的,JDK技术栈大分类 |
13 |
【方向盘】-Servlet |
Servlet规范、Web相关内容专题 |
14 |
【方向盘】-Java EE |
从Java EE到Jakarta EE,30年弹指一挥间 |
15 |
【方向盘】-工具/提效 |
开发工具、软件工具,目标是提效 |
16 |
【方向盘】-Spring技术栈新特性 |
Spring Framework、Spring Boot、Spring Cloud、Spring其它技术 |
17 |
【方向盘】-基本功 |
每个Javaer,都需要有扎实的基本功 |
… |
… |
… |
99 |
源代码库 |
大多数专栏均配有源代码,都在这里 |