侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 285 篇文章
  • 累计创建 125 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

java的系统参数和运行参数以及springboot3种参数的实战指南

孔子说JAVA
2022-05-29 / 0 评论 / 2 点赞 / 112 阅读 / 8,720 字 / 正在检测是否收录...

java命令启动java应用时首先会启动 java 运行时环境JRE,然后加载指定的类,调用类的 main 方法。在通过java命令启动应用时,有一系列的可选参数,按类别区分为系统参数和运行参数,它们在java命令中的位置与使用方式是有区别的,本教程主要介绍java命令中这2种参数的使用方式及区别,以及springboot项目中3大参数的用法。

1、java程序的入口方法

main()方法是java程序的入口方法,是JVM能够识别的特殊方法名,当程序开始运行时,Java虚拟机(JVM)会首先查找main()方法。该方法必须定义为 public static 类型,并且不返回任何值,参数为 String 类型的数组,最常用的定义形式为:public static void main(String[] args),还有一些其他的定义形式如下:

public static void main(String[] args)
static public void main(String[] args)
public static final void main(String[] args)
static public synchronized void main(String[] args)

2、java的启动参数

2.1 java程序的启动命令

java 命令支持两种启动方式,一种是指定要执行的 java 类,另一种是指定要执行的 jar 包,具体语法如下:

// 指定要执行的 java 类
java [options] classname [args]

// 指定要执行的 jar 包
java -jar [options] *.jar [args]

上述命令中每一项的含义如下:

  • options 是可选项,选项之间使用空格分割,配置 java 系统参数
  • classname 是要加载的类的名字
  • filename 是要执行的 java 压缩文件(JAR)的名字,需要和 -jar 搭配使用
  • args 是传递给 main() 方法的参数,使用空格分割,配置 java 运行参数

从上面的语法说明中可以看出来,在通过 java 命令启动应用时,有一系列的可选参数,包括系统参数和运行参数,使用时可以根据应用场景选择合适的参数。

2.2 系统参数(VM option)

java的系统参数(VM option)为java中的系统级全局变量,该参数在程序中任何位置都可以访问到。优先级最高,覆盖程序中同名配置。

要特别注意的是:该参数的位置是在java命令中的 classname*.jar 之前,要是放在java类或jar包后面是不起作用的。

2.2.1 系统参数的语法格式

系统参数的标准语法格式为:-Dargname=argvalue,多个参数之间用空格隔开,如果参数值中间有空格,则用引号括起来。其中 argname 表示参数名,argvalue 表示参数值,-D 表示这个参数是java的系统参数,为固定写法,注意字母 D 必须大写。

参数名 argname 可以是 Java 默认的,此类参数由 JVM 虚拟机自动识别并生效,例如,-Dfile.encoding=UTF-8 用于指定文件编码格式;也可以是用户自定义的,例如,-Dmy=user,程序中可以读取该参数值,执行相关逻辑。

系统参数中设置的参数键值对,在程序中可以用 System.getProperty("propertyName") 来获取对应的参数值。

2.2.2 系统参数的示例1 - 不带包名的java文件

首先创建一个名为 JavaParam.java 的文件,内容如下:

public static void main(String[] args) {
    String result = System.getProperty("vmparam");
    System.out.println("vmparam: " + result);
}

打开dos窗口,我们编译下该文件并带上系统参数 vmparam 执行一下看效果:

  1. 编译java文件
# cd到 JavaParam.java 文件所在的目录,执行下面的编译命令:
javac JavaParam.java

# 如果代码中有中文,因java文件的保存编码格式不同,有时会提示 “java编译命令 错误: 编码 GBK 的不可映射字符..”,可以在编译命令中指定编码格式如下
javac -encoding UTF-8 JavaParam.java
  1. 执行/运行生成的class文件,这里注意系统参数是在java文件的前面
java -Dvmparam=test JavaParam

image-1653646286698

2.2.3 系统参数的示例2 - 带包名的java文件

上述例子中的java代码没有包名(package),如果代码中包含包名,则java执行命令有所区别:

首先创建一个名为 JavaParam.java 的文件,与上例的区别仅仅是加了package包名,内容如下:

package com.test;

public class JavaParam {
    public static void main(String[] args) {
        String result = System.getProperty("vmparam");
        System.out.println("vmparam: " + result);
    }
}

有包的java程序,如果用上例的 java -Dvmparam=test JavaParam命令来执行会失败,这是由于我们没有指定classpath,jvm准备在当前路径下查找JavaParam.class来装载,找了一圈没找到(确实有个JavaParam类,但是A类的完整路径是com.test.JavaParam,所以不是这个),报错找不到或无法加载主类。需要用完整包名来执行。

  1. 编译java文件,我们可以使用 -d . 来让编译器以当前路径为基准,自动创建包路径,这个 -d . 放在命令的前面或后面都可以。
# cd到 JavaParam.java 文件所在的目录,执行下面的编译命令:
javac -d . JavaParam.java

# 也可以把 -d . 放在后面
javac JavaParam.java -d .

# 如果代码中有中文,因java文件的保存编码格式不同,有时会提示 “java编译命令 错误: 编码 GBK 的不可映射字符..”,可以在编译命令中指定编码格式如下
javac -encoding UTF-8 -d . JavaParam.java
  1. 执行/运行生成的class文件,这里注意系统参数是在java文件的前面。同时要指定java类的完整包名。
java -Dvmparam=test com.test.JavaParam

image-1653648102985

多个系统参数示例:

java -Dvmparam=test -Dfile.encoding=UTF-8 com.test.JavaParam

2.3 运行参数

main()方法执行时传入的参数值即为运行参数,如果参数有多个,用空格分开。main()方法的参数 String[] args 就是存储运行参数的变量,在程序中可以直接使用。

2.3.1 运行参数的语法格式

运行参数的标准语法格式为:argvalue,只需要指定参数值即可,多个参数值之间用空格隔开,如果参数值中间有空格,则用引号括起来。

2.3.2 运行参数的示例

首先创建一个名为 JavaParam.java 的文件,内容如下:

package com.test;

public class JavaParam {
    public static void main(String[] args) {
        //获取系统参数
        String vmParam = System.getProperty("vmOption");
        System.out.println("vmOption的参数为:" + vmParam);
        //获取main方法的参数即运行参数
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + (i+1) + "个参数为: " + args[i]);
        }
    }
}
  1. 编译java文件,我们可以使用 -d . 来让编译器以当前路径为基准,自动创建包路径,这个 -d . 放在命令的前面或后面都可以。
# cd到 JavaParam.java 文件所在的目录,执行下面的编译命令:
javac -encoding UTF-8 -d . JavaParam.java
  1. 执行/运行生成的class文件,这里注意系统参数是在java文件的前面。同时要指定java类的完整包名。有3个运行参数a、b、c在java类的后面。
java -DvmOption=test com.test.JavaParam a b c

image-1653649561426

2.4 系统参数和运行参数的区别

通过上⾯的⽰例我们已经发现使⽤系统参数和运行参数时,系统参数是紧随 java 之后的(如果是执行的jar包,那就是跟在 java -jar 之)后。而运行参数则是跟在java类名 JavaParam 之后(如果是执行的jar包,那就是跟在 xxx.jar 之后)。如果不按照顺序执行,要么参数不被识别,要么就会报异常。

例如:java JavaParam -DvmOption=test,这里的参数 -DvmOption=test 我们的本意是将 vmOption=test 作为系统参数,而这里程序是将 -DvmOption=test 整个作为运行参数的。

再举个例子:java a b c JavaParam,我们将运行参数 a b c 放在执行类 JavaParam 的前面,则程序会报错“找不到或无法加载主类 a”。

2.5 IDEA 中的参数设置(系统参数和运行参数)

  1. 新建java文件

在idea中新建一个项目demo,在demo项目中新建一个名为 JavaParam.java 的文件,内容如下:

package com.kz.example.common.test;

/**
 * java系统参数和运行参数
 */
public class JavaParam {
    public static void main(String[] args) {
        //获取系统参数
        String vmParam = System.getProperty("vmParam");
        System.out.println("vmParam的参数/系统参数为:" + vmParam);
        //获取main方法的参数即运行参数
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + i + "个运行参数为: " + args[i]);
        }
    }
}
  1. IDEA 中的参数设置

通过菜单 Run -> Edit Configurations 打开配置页面,在Application下选中 JavaParam 类,点击 Modify options,在展开的下拉列表中选中 Add VM options 选项,表示在配置列表中展示系统参数。

  • 也可以在java类上右键选择 More Run/Debug -> Modify Run Configuration... 进入配置页面。

image-1653650600459

VM options 中设置系统参数,Program arguments 中设置运行参数。

image-1653650735064

系统参数设置为-DvmParam="hello" -Dfile.encoding=UTF-8(可以设置1个或多个参数,多个参数以空格分开),运行参数设置为 aa bb cc dd设置后的内容如下:

image-1653651139821

在java类上右键选择 run 'JavaParam.main()' 运行java,执行结果如下:

image-1653651486476

可以看到系统参数和运行参数都输出了期望的结果。

3、springboot的启动命令参数

3.1 springboot项目配置

假设我们有一个springboot项目(自己可以新建一个或利用已有的项目测试),配置文件application.yml 部分内容如下:

#端口,项目上下文
server:
  port: 8080
  servlet:
    context-path: /demo

# springboot多环境配置
# 默认启动的是测试环境配置
spring:
  profiles:
    active: test
    
# 自定义的参数
myParam: on

可以使用命令 java -jar demo.jar 来启动Spring Boot项⽬,这时候项目的访问端口为8080。

可以在启动参数里修改配置文件中配置的参数。

我们也可以在命令中使用参数来指定端口号,如 java -jar demo.jar --server.port=8081,这时配置文件中的8080端口就不起作用了,项目是以8081的端口启动,可见通过命令⾏传递的参数具有更⾼的优先级,会覆盖同名的其他配置参数。

默认情况下Spring Boot使⽤8080端⼝,通过上述参数将其修改为8081端⼝,⽽且通过命令⾏传递的参数具有更⾼的优先级,会覆盖同名的其他配置参数。

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

  • 选项参数
  • ⾮选项参数/运行参数
  • 系统参数

3.2 选项参数

选项参数,也叫命令行参数,在启动Spring Boot项⽬时,我们可以通过选项参数来传递项目的一些配置参数:

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

这时配置文件中的8080端口就不起作用了,项目是以8081的端口启动,可见通过命令⾏传递的参数具有更⾼的优先级,会覆盖同名的其他配置参数。这里的 --server.port=8081 就是选项参数。通过 --server.port 来设置应⽤程序的端⼝。其配置作⽤等价于在application.properties中配置的 server.port=8081,但是优先级会更高。

  • 选项参数的基本格式为 --name=value(注意这里“–”为连续的两个减号)。

选项参数的获取

选项参数可以直接通过 @Value 注解在类中获取,该注解的参数形式为 ${paramName},示例如下:

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

选项参数和⾮选项参数均可以通过ApplicationArguments接⼝获取,具体用法参考非选项参数/运行参数部分。

3.3 ⾮选项参数/运行参数

⾮选项参数的使⽤⽰例如下:

java -jar xxx.jar abc def 

上述⽰例中,“abc”和“def”便是⾮选项参数,也叫运行参数。

⾮选项参数/运行参数的获取

选项参数和⾮选项参数(也叫运行参数)均可以通过 ApplicationArguments 接⼝获取,具体获取⽅法直接在使⽤参数的类中注⼊ ApplicationArguments 接⼝即可,具体示例如下。

//此处springboot启动的时候传入参数
SpringApplication.run(Application.class, args);

@RestController
public class ArgumentsController {
  @Resource
  private ApplicationArguments arguments;
  
  // 获取参数
  public void getArgs() {
  	 List<String> params = arguments.getNonOptionArgs();
    for(int i=0;i<params.size();i++){
      System.out.println(params.get(i));
    }
  }
}

3.4 系统参数

系统参数,该参数会被设置到系统变量中,系统参数的标准语法格式为:-Dargname=argvalue,多个参数之间用空格隔开,如果参数值中间有空格,则用引号括起来。其中 argname 表示参数名,argvalue 表示参数值,-D 表示这个参数是java的系统参数,为固定写法,注意字母 D 必须大写。使⽤⽰例如下:

  • 注意:通过 -D 传递系统参数时,务必放置在待执⾏的jar包之前。
java -jar -Dserver.port=8081 xxx.jar

系统参数的获取

系统参数可以通过java.lang.System提供的⽅法获取,具体如下:

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

3.5 参数的区别

关于参数的区别,重点看选项参数和系统参数。通过上⾯的⽰例我们已经发现使⽤选项参数和系统参数时,选项参数在命令中是位于 xxx.jar 之后传递的,⽽系统参数是紧随java -jar 之后的。如果不按照顺序执行,要么参数不被识别,要么就会报异常。

  • 选项参数在命令中是位于 xxx.jar 之后传递的。
  • 系统参数在命令中是紧随 java -jar 之后的。

⽐如使⽤如下⽅式使⽤选项参数:

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

则会抛出如下异常:

Unrecognized option: --server.port=8081
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

如果将系统参数放在jar包后⾯,问题会更严重。会出现可以正常启动,但参数⽆法⽣效。这也是为什么有时候明明传递了参数但是却未⽣效,那很可能是因为把参数的位置写错了。

3.6 参数的优先级

对于同一个参数,我们可以使用不同的方式进行传递,如springboot的环境配置参数 spring.profiles.active ,既可以使用系统参数来传递,也可以使用选项参数来进行。

方式一:使用系统参数

java -jar -Dspring.profiles.active=prod demo.jar

执行上述命令时,如果我们在程序中输出参数 spring.profiles.activemyParam 的值,可以看到 spring.profiles.active 的值为 prodmyParam 的值为 on。这2个值在 application.yml 的配置为 teston,可以在 ## 3.1 springboot项目配置 部分查看具体配置。

可以看出,系统参数的优先级高于配置文件中定义的变量。

拓展:命令行的系统参数在配置文件中可以使用如下方式使用,如 spring.profiles.active:${spring.profiles.active},又如下例:

server:
  port: 8080
  servlet:
    # 应用的访问路径,api.path可以由系统参数指定,这里表示访问路径默认取api.path的值,如果不存在则取 / 这个值。
    context-path: ${api.path:/}

方式二:使用选项参数

java -jar demo.jar --spring.profiles.active=prod --myParam=off

执行上述命令时,如果我们在程序中输出参数 spring.profiles.activemyParam 的值,可以看到 spring.profiles.active 的值为 prodmyParam 的值为 off

可以看出,选项参数的优先级高于配置文件中定义的变量。

方式三:同时使用系统参数和选项参数

java -jar -DmyParam='test1' demo.jar --spring.profiles.active=prod --myParam='test2'

执行上述命令时,如果我们在程序中输出参数 spring.profiles.activemyParam 的值,可以看到 spring.profiles.active 的值为 prodmyParam 的值为 test2

可以看出,选项参数的优先级高于系统参数。

总结:

由上可以得出结论,Springboot加载参数的优先级如下:

配置文件变量 < 系统参数(JVM系统变量) < 选项参数(命令行参数)

3.7 IDEA中添加启动参数

通过菜单 Run -> Edit Configurations 打开配置页面,在Application下选中 JavaParam 类,点击 Modify options,在展开的下拉列表中选中 Add VM options 选项,表示在配置列表中展示系统参数。

  • 也可以在java类上右键选择 More Run/Debug -> Modify Run Configuration... 进入配置页面。

image-1655165217423

VM options 选项中填写系统参数 -Dspring.profiles.active=test -Dserver.port=8081 或者在 Environment variables 选项中填写选项参数(命令行参数) spring.profiles.active=test;server.port=8081,二者选一即可(这两种写法的效果是一样的)。

上述方式对应的命令如下(即可以用下方的命令行直接启动应用),

第一种,只使用系统参数:

java -jar -Dspring.profiles.active=test -Dserver.port=8081 app.jar

第二种,只使用命令行参数

java -jar app.jar --spring.profiles.active=test --server.port=8081

第三种,混合使用系统参数和命令行参数

java -jar -Dspring.profiles.active=test app.jar --server.port=8081
2

评论区