spring boot打的包直接运行

Spring Boot 提供了一个插件 spring-boot-maven-plugin 把程序打包成一个可执行的jar包,直接执行java -jar xxx.jar即可以启动程序

1、引用 spring-boot-maven-plugin插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

2、打包文件内部结构

  1)、BOOT-INF:

                class:项目代码

                lib:依赖jar包

    2)、META-INF:程序入口

                maven.xxx:程序配置文件

                MANIFEST.MF

    3)、org.springframework.boot.loader

3、MANIFEST.MF

Manifest-Version: 1.0
Implementation-Title: sk-cloud-order-sc
Implementation-Version: 1.0-SNAPSHOT
Start-Class: com.sk.order.sc.app
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 1.4.3.RELEASE
Created-By: Maven JAR Plugin 3.2.2
Main-Class: org.springframework.boot.loader.JarLauncher

    Main-Class:org.springframework.boot.loader.JarLauncher:当我们使用java -jar xxx.jar启动jar包的时候通过调用JarLauncher#Main方法,不是我们定义的Main方法。SpringBoot内部提供一个可用于执行SpringBootApplication的工具类,这就是为什么打的包包含spring-boot-loader

    

4、JarLauncher源码查看

      1)、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-loader</artifactId>
    <version>2.7.8</version>
</dependency>

       2)、抽象Launcher类

 用于启动应用程序,分别有JarLauncher、WarLauncher、PropertiesLauncher实现类

public abstract class Launcher {
    private static final String JAR_MODE_LAUNCHER = "org.springframework.boot.loader.jarmode.JarModeLauncher";

    public Launcher() {
    }

    protected void launch(String[] args) throws Exception {
        if (!this.isExploded()) {
            JarFile.registerUrlProtocolHandler();
        }

        ClassLoader classLoader = this.createClassLoader(this.getClassPathArchivesIterator());
        String jarMode = System.getProperty("jarmode");
        String launchClass = jarMode != null && !jarMode.isEmpty() ? "org.springframework.boot.loader.jarmode.JarModeLauncher" : this.getMainClass();
        this.launch(args, launchClass, classLoader);
    }

    protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
        Thread.currentThread().setContextClassLoader(classLoader);
        this.createMainMethodRunner(launchClass, args, classLoader).run();
    }

    //Archive相关代码
}

    3)、Archive:归档文件获取Mainifest等URL路径(jar包中包含jar,或者jar包中class文件,那么会使用 !/ 分隔开)

public class JarFileArchive implements Archive {

    public URL getUrl() throws MalformedURLException {
        return this.url != null ? this.url : this.jarFile.getUrl();
    }

    public Manifest getManifest() throws IOException {
        return this.jarFile.getManifest();
    }
}
  4)、JarFile:jar包封装文件
    5)、JarLauncher启动流程
JarLauncher#main -> Launcher#launch ->MainMethodRunner#run ->获取manifest文件Start-Class类通过反射调用main方法
public class JarLauncher extends ExecutableArchiveLauncher {
    static final Archive.EntryFilter NESTED_ARCHIVE_ENTRY_FILTER = (entry) -> {
        return entry.isDirectory() ? entry.getName().equals("BOOT-INF/classes/") : entry.getName().startsWith("BOOT-INF/lib/");
    };

    public JarLauncher() {
    }

    protected JarLauncher(Archive archive) {
        super(archive);
    }

    protected boolean isPostProcessingClassPathArchives() {
        return false;
    }

    protected boolean isNestedArchive(Archive.Entry entry) {
        return NESTED_ARCHIVE_ENTRY_FILTER.matches(entry);
    }

    protected String getArchiveEntryPathPrefix() {
        return "BOOT-INF/";
    }

    public static void main(String[] args) throws Exception {
        (new JarLauncher()).launch(args);
    }
}

 Launcher#launch

protected void launch(String[] args) throws Exception {
    if (!this.isExploded()) {
        JarFile.registerUrlProtocolHandler();
    }
    //自定义类加载器加载jar文件(通过active的urls加载jar文件)
    ClassLoader classLoader = this.createClassLoader(this.getClassPathArchivesIterator());
    String jarMode = System.getProperty("jarmode");
    //获取manifest文件的Start-Class类
    String launchClass = jarMode != null && !jarMode.isEmpty() ? "org.springframework.boot.loader.jarmode.JarModeLauncher" : this.getMainClass();
    //调用Start-Class类类main方法
    this.launch(args, launchClass, classLoader);
}

protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
    Thread.currentThread().setContextClassLoader(classLoader);
    this.createMainMethodRunner(launchClass, args, classLoader).run();
}

/*
* 调用manifest文件Start-Class类mian方法
*/
public class MainMethodRunner {
    private final String mainClassName;
    private final String[] args;

    public MainMethodRunner(String mainClass, String[] args) {
        this.mainClassName = mainClass;
        this.args = args != null ? (String[])args.clone() : null;
    }

    public void run() throws Exception {
        Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
        Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
        mainMethod.setAccessible(true);
        mainMethod.invoke((Object)null, this.args);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LED显示屏的智能化发展与未来趋势

摘要&#xff1a;随着智能化技术的飞速发展&#xff0c;LED显示屏行业也迎来了新的变革。本文将探讨LED显示屏的智能化发展方向&#xff0c;包括人屏互动、大屏中控智能化&#xff0c;以及智能LED显示屏在不同领域的应用前景。 1、引言 在智能化浪潮的推动下&#xff0c;LED显示…

GPT-4o: 未来的智能助手

GPT-4o: 未来的智能助手 在这个信息爆炸的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为我们生活中不可或缺的一部分。作为OpenAI最新推出的语言模型&#xff0c;GPT-4o不仅继承了前几代模型的优点&#xff0c;还在多个方面进行了显著的提升。本文将带你深入了解…

家政预约小程序03分类管理

目录 1 创建数据源2 搭建导航菜单3 搭建小程序4 设置变量5 变量绑定总结 家政预约小程序里&#xff0c;在首页需要展示家政可以开展的各类业务。我们把业务按照类别进行划分&#xff0c;本篇我们介绍一下管理后台的维护功能以及小程序的展示功能。 1 创建数据源 为了管理和展示…

WiFi蓝牙模块开发配置过程中需要注意的细节

在很多产品的应用场景中&#xff0c;WIFI网络会给我们提供很多便捷&#xff0c;MCU开发中大多使用串口WIFI蓝牙模块来实现产品接入WIFI网络中。   具体的使用模型如下图所示&#xff1a;整个系统涉及到WIFI网络、手机、服务器平台以及我们设计的产品&#xff0c;一个完整的生…

uniapp+php服务端实现苹果iap内购的消耗性项目和非续期订阅项目,前后端代码加逻辑分析

前言&#xff1a;公司的项目app在上架苹果商店时发现人家要求里面的部分购买项目必须使用iap购买的方式&#xff0c;使用原本的微信支付方式审核不给通过&#xff0c;无奈只能重新研究这个东西。做起来还是有点麻烦&#xff0c;主要是网上的文章很少&#xff0c;不能直接硬抄。…

彩信JSON接口对接发送

随着通讯技术的飞速发展&#xff0c;传统的短信已经无法满足人们日益增长的沟通需求。在这样的背景下&#xff0c;群发彩信作为一种更为先进、更为丰富的信息传递方式&#xff0c;逐渐受到了企业和个人的青睐。那么&#xff0c;群发彩信应该怎么对接&#xff0c;又具体有哪些优…

经常碰到的20个等待事件

经常碰到的20个等待事件 oracle等待事件简介 DBA团队维护的部分应用运行在oracle数据库平台&#xff0c;为及时了解数据库的运行情况&#xff0c;需要建立涵盖各个维度的监控体系&#xff0c;包括实例状态、空间使用率、ORA错误等数十项监控指标。这其中有一个有效判断数据库…

Parasoft C++Test软件静态分析操作指南_软件质量度量

系列文章目录 Parasoft CTest软件安装指南 Parasoft CTest软件静态分析操作指南_编码规范/标准检查 Parasoft CTest软件静态分析操作指南_软件质量度量 Parasoft CTest软件静态分析_自动提取静态分析数据生成文档 Parasoft CTest软件单元测试_操作指南 Parasoft CTest软件单元…

Mqtt_Java_IDEA中编写“发布者”和“订阅者”

1Java创建项目 2导入依赖 将下面Mqtt的库名复制到 <dependencies> 下面 <dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.client.mqttv3</artifactId><version>1.2.5</version></d…

20212416 2023-2024-2 《移动平台开发与实践》第5次作业

百度地图应用 1.实验内容2.实验过程2.1 Android Studio配置2.1. 创建一个Android项目2.2 在项目中本地集成BaiduMap SDK 2.2 编写代码2.2.1 配置AndroidManifest.xml文件2.2.2 编写UI界面布局文件2.2.3 编写主函数代码2.2.4 运行结果 3.学习中遇到的问题及解决4.学习感悟与思考…

netdiscover一键收集子网内的所有信息(KALI工具系列六)

目录 1、KALI LINUX简介 2、netdiscover工具简介 3、在KALI中使用netdiscover 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 扫描子网整个网段 4.2 指定网卡进行扫描 4.3 扫描网卡的公共网络 4.4 快速扫描网卡的公共lan地址 4.5 设置…

网络拓扑—DHCP服务配置

文章目录 DHCP服务搭建相关配置细节前提安装DHCP服务 DHCP服务搭建 相关配置细节前提 系统&#xff1a;Windows Server 2003 IP网段&#xff1a;10.0.0.0/24 三台机子&#xff1a; 普通PC机 DHCP服务器 路由器&#xff08;两块网卡&#xff0c;连接内外网&#xff09; //注…

Java进阶学习笔记6——继承的介绍

继承的学习目标&#xff1a; 认识继承&#xff1b; 继承的好处、应用场景 什么是继承&#xff1f; Java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;可以让一个类和另外一个类建立父子关系。 继承的特点: 子类能继承父类的非私有成员&#xff08;成员变…

利用sql注入对某非法网站的渗透

本文仅用于技术讨论&#xff0c;切勿用于违法途径&#xff0c;且行且珍惜&#xff0c; 所有非经授权的渗透&#xff0c;都是违法行为 前言 这段时间一直在捣鼓sql注入&#xff0c;最近又通过一个sql注入点&#xff0c;成功进入某个非法网站的后台&#xff0c;拿到整个网站的…

mac版本Phpstudy本地环境安装Discuz教程【2024】

此方法适用于m1版本的mac版本Phpstudy本地环境安装Discuz&#xff0c;当然同样使用更高版本的mac端。网上各种安装教程参差不齐&#xff0c;根本解决不了小白的入门需求&#xff0c;以下是最新且直接明了的安装教程。 Phpstudy本地环境安装Discuz教程&#xff1a; 1、安装Phps…

渗透测试 一个很奇怪的支付漏洞

新手实战刷课网站、好玩又有趣&#xff01; 第一步 打开网站、任意账户名密码登陆发现验证码可重复利用 这时候我们可以试试admin账号、发现如果账号正确会提示账户已存在、反之回显账户密码错误 第二步 既然验证码可以重复利用&#xff1b;而且账号名有回显 这时候我们试…

安装harbor出现问题: Running 1/1 ✘ Network harbor_harbor Error

安装harbor出现问题&#xff1a; [] Running 1/1 ✘ Network harbor_harbor Error 0.2s failed to create network harbor_harbor: Error response from daemon: Fa…

数据结构和算法基础(一)

数据结构——基本概念 数据&#xff1a;数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 数据元素、数据项&#xff1a;数据元素是数据的基本单位&#xff0c;通常作为…

Ansible实战YAML语言完成apache的部署,配置,启动全过程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f3dd;️Ansible专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年5月24日15点59分 目录 &#x1f4af;趣站推荐&#x1f4af; &#x1f38a;前言 ✨️YAML语言回顾 &#x1f386;1.编写YAML文…

嵌入式作业5

在函数main.c中初始化三种颜色的灯&#xff1a; gpio_init(LIGHT_BLUE, GPIO_OUTPUT, LIGHT_OFF); //蓝灯 gpio_init(LIGHT_GREEN, GPIO_OUTPUT, LIGHT_OFF); //绿灯 gpio_init(LIGHT_RED, GPIO_OUTPUT, LIGHT_OFF); //红灯 同时为了响应以上修改&#xff0c;进入isr。c…