Spring Boot命令行启动添加参数

news2024/11/16 11:58:09

一、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的相关源码解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试 JavaScript 实现【最优策略组合下的总的系统消耗资源数】【牛客练习题】,附详细解题思路

一、题目描述 在通信系统中有一个常见的问题是对用户进行不同策略的调度&#xff0c;会得到不同系统消耗的性能。 假设由N个待串行用户&#xff0c;每个用户可以使用A/B/C三种不同的调度策略&#xff0c;不同的策略会消耗不同的系统资源。 请你根据如下规则进行用户调度&…

【Java-SpringBoot+Vue+MySql】Day3.2-RESTful风格

目录 一、RESTful风格介绍 1、知识轰炸 2、代码演练 &#xff08;1&#xff09;测试get接口 &#xff08;2&#xff09;测试Post接口 &#xff08;3&#xff09;测试Put接口 &#xff08;4&#xff09;测试delete接口 二、Swagger介绍 1、知识轰炸 2、实操演练 &#x…

Android修行手册-多路USB外接摄像头

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

CSS3-盒子模型

盒子模型的介绍 盒子概念 盒子组成 盒子内减 拓展 1. 盒子的概念 1 页面中的每一个标签&#xff0c;都可看做是一个 “盒子”&#xff0c;通过盒子的视角更方便的进行布局 2 浏览器在渲染&#xff08;显示&#xff09;网页时&#xff0c;会将网页中的元素看做是一个个的矩形区域…

Selenium详解

Selenium 环境配置好之后&#xff0c;我们就可以使用 Selenium 来操作浏览器&#xff0c;做一些我们想做的事情了。在我们爬取网页过程中&#xff0c;经常发现我们想要获得的数据并不能简单的通过解析 HTML 代码获取&#xff0c;这些数据是通过 AJAX 异步加载方式或经过 JS 渲染…

Python高级系列教程:Python闭包和装饰器

今天我们将继续讲解 Python 中的闭包和装饰器。虽然我们还没有详细学习这两个概念&#xff0c;但在面向对象编程中&#xff0c;我们已经经常使用装饰器了。装饰器可以给函数增加额外的功能&#xff0c;就像语法糖一样甜。在 Python 中&#xff0c;装饰器的格式通常是在函数上方…

三分钟学习一个python小知识1-----------我的对python的基本语法的理解

文章目录 一、变量定义二、数据类型三、条件语句四、循环语句五、函数定义总结 一、变量定义 在Python中&#xff0c;使用等号&#xff08;&#xff09;进行变量的定义&#xff0c;并不需要声明变量的类型&#xff0c;Python会自动根据赋值的数据类型来判断变量的类型&#xf…

算法篇——动态规划 完全和多重背包问题 (js版)

一些分析总结 01 背包 问题和 完全背包 问题的不同点在于&#xff0c;所有的物品只能使用一次&#xff0c;判断 哪些物品 装进背包里 物品价值和 最大&#xff1b;而 完全背包 问题中&#xff0c;所有物品都能使用n次&#xff0c;判断 哪个物品 装 n 个进去 物品价值和 最大。…

Mybatis源码分析_日志模块 (1)

不得不承认&#xff0c;学习MyBatis的时间成本要比学习Spring低很多&#xff0c;Mybatis是我所了解过的代码量最小、整体架构最简单&#xff0c;但是又是最具有学习价值的一个框架。如果&#xff0c;你想快速的阅读一个框架的源码&#xff0c;并且掌握这个框架的精髓&#xff0…

浅析GeoServer CVE-2023-25157 SQL注入

简介 GeoServer是一个开源的地图服务器&#xff0c;它是遵循OpenGIS Web服务器规范的J2EE实现&#xff0c;通过它可以方便的将地图数据发布为地图服务&#xff0c;实现地理空间数据在用户之间的共享。 影响版本 geoserver<2.18.7 2.19.0<geoserver<2.19.7 2.20.0…

国内外八大敏捷开发工具盘点

1、Leangoo领歌&#xff1b;官网&#xff1a;Leangoo领歌 - 高效企业必备的敏捷工具,Scrum工具,SAFe敏捷工具,敏捷项目管理,敏捷研发工具 2、VersionOne&#xff1b;官网&#xff1a;https://www.collab.net/products/versiononehttps://www.collab.net/products/versionone …

Python高级系列教程:Python高级语法与正则表达式

学习目标 1、能够掌握with语句的使用 2、能够知道生成器的两种创建方式 3、能够知道深拷贝和浅拷贝的区别 4、能够掌握Python中的正则表达式编写 一、Python高级语法 1、with语句和上下文管理器 ☆ with语句 Python提供了 with 语句的写法&#xff0c;既简单又安全。文件操…

Vue-scoped(局部)样式

scoped(局部)样式 scoped是在脚手架有一个编写样式的小技巧 作用&#xff1a;让样式在局部生效&#xff0c;防止冲突 1 编写案例 现在有两个组件&#xff0c;一个student,一个school&#xff0c;现在想给组件写点样式 这里只给个背景色 没问题&#xff0c;样式生效 2 样式冲…

docker canal 安装

(373条消息) 使用 Docker 部署 canal 服务_canal docker部署_qq2276031的博客-CSDN博客https://blog.csdn.net/qq2276031/article/details/120234122 docker canal github 网址 Canal Admin Docker alibaba/canal Wiki (github.com)https://github.com/alibaba/canal/wiki/Ca…

璞华产业园区租赁运营平台,助力空间资产管理数字化转型!

{ 产业园区租赁运营平台 } 直面行业痛点 专注技术创新 点击输入图片描述&#xff08;最多30字&#xff09; 产业园区作为产业转型升级的重要载体&#xff0c;产业园区租赁运营也正迎来新的发展机遇。璞华一直关注为客户智能化转型过程中提供的服务&#xff0c;能否将技术方案…

【自监督论文阅读 3】DINOv1

文章目录 一、摘要二、引言三、相关工作3.1 自监督学习3.2 自训练与知识蒸馏 四、方法4.1 SSL with Knowledge Distillation4.2 教师网络4.3 网络架构4.4 避免坍塌 五、实验与评估六、消融实验6.1 不同组合的重要性6.2 教师网络选择的影响6.3 避免坍塌6.4 在小batch上训练 七、…

elk搭建

1、前言 ELK 是一个开源的日志管理解决方案&#xff0c;主要是为了统一收集生产的日志&#xff0c;方便日志的查询&#xff0c;传统的日志都是保存在每个机器上&#xff0c;当要查询的时候&#xff0c;需要到每一台机器上去查询日志&#xff0c;非常麻烦&#xff0c;而elk则使…

阿里巴巴 Java 开发手册部分整理

阿里巴巴 Java 开发手册 一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 集合处理(六) 并发处理(七) 控制语句(八) 注释规约(九) 其它 二、异常日志(一) 异常处理(二) 日志规约 三、单元测试四、安全规约五、MySQL 数据库(一) 建表规约(二) 索引规约(三…

Java 操作pdf工具类

1、获取pdf页数 添加maven依赖&#xff1a; <!-- java获取Pdf文件页码 --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>1.8.11</version></dependency>代码实现&#x…

Goby 漏洞发布|电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞

漏洞名称&#xff1a;电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞 English Name&#xff1a;Telecom system /manager/teletext/material/upload.php fileupload vulnerability CVSS core: 9.8 影响资产数&#xff1a;856 漏洞描述&…