怎么在SpringBoot中启动java-jar命令

这期内容当中小编将会给大家带来有关怎么在Spring Boot 中启动java -jar命令,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

创新互联2013年至今,先为湖南等服务建站,湖南等地企业,进行企业商务咨询服务。为湖南企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

jar包目录和jar命令启动入口

在正式开始之前,我们先来看看把jar包进行解压。然后用tree /f命令查看目录结构(由于笔者写博文时用的是window,所以用的是tree /f命令),由于目录结构太长,这里做了相应省略,如下:

├─BOOT-INF
│ ├─classes
│ │ │ application.properties
│ │ │
│ │ └─com
│ │   └─spring
│ │     └─boot
│ │       └─test
│ │           SpringBootTestApplication.class
│ │
│ └─lib
│     classmate-1.5.1.jar
│     hibernate-validator-6.0.18.Final.jar
│     …………此处省略…………
│
├─META-INF
│ │ MANIFEST.MF
│ │
│ └─maven
│   └─com.spring.boot.test
│     └─spring-boot-test
│         pom.properties
│         pom.xml
│
└─org
  └─springframework
    └─boot
      └─loader
        │ ExecutableArchiveLauncher.class
        │ JarLauncher.class
        │ LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
        │ LaunchedURLClassLoader.class
        │ Launcher.class
        │ MainMethodRunner.class
        │ PropertiesLauncher$1.class
        │ PropertiesLauncher$ArchiveEntryFilter.class
        │ PropertiesLauncher$PrefixMatchingArchiveFilter.class
        │ PropertiesLauncher.class
        │ WarLauncher.class
        │
        ├─archive
        │   Archive$Entry.class
        │   …………此处省略…………
        │
        ├─data
        │   RandomAccessData.class
        │   …………此处省略…………
        │
        ├─jar
        │   AsciiBytes.class
        │   Bytes.class
        │   …………此处省略…………
        │
        └─util
            SystemPropertyUtils.class

先简单说下上面目录结构,大体目录分三层:BOOT-INF、META-INF、org,BOOT-INF是存放对应的应用服务的.class文件和Maven依赖的jar包,包括启动类SpringBootTestApplication,META-INF下存放的是Maven相关的pom信息和MANIFEST.MF文件,org文件夹下存放的是Spring boot loader模块编译的.class文件,也就是jar启动的关键代码所在。

在执行java -jar命令的时候,它的启动类配置实在jar包目录下META-INF文件夹下的名MANIFEST.MF文件中,在这个文件中有一个名为Main-Class的属性,我们来看下这个文件的具体内容:

Manifest-Version: 1.0
Implementation-Title: spring-boot-test
Implementation-Version: 0.0.1-SNAPSHOT
Start-Class: com.spring.boot.test.SpringBootTestApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.2.3.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.JarLauncher

从上面的配置文件中,可以看到Main-Class属性指向的Class为org.springframework.boot.loader.JarLauncher,而JarLauncher是JAR的启动器,这个类是在org/springframework/boot/loader/,然后可以看到项目所定义的启动类是指向Start-Class这个属性的。

JAR文件启动器——JarLauncher

在上面我们说了JarLauncher是JAR可执行的启动器,那么它和项目的启动类SpringBootTestApplication有什么关联呢?先给大家来个示例,先来到解压目录下执行命令:java org.springframework.boot.loader.JarLauncher ,然后便是如下界面:

C:\Users\elisha\Desktop\spring-boot-test-0.0.1-SNAPSHOT>java org.springframework.boot.loader.JarLauncher
 
 .  ____     _      __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/ ___)| |_)| | | | | || (_| | ) ) ) )
 ' |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::    (v2.2.3.RELEASE)
2020-01-18 14:28:19.866 INFO 3644 --- [      main] c.s.boot.test.SpringBootTestApplication : Starting SpringBootTestApplication on LAPTOP-R2NNI9CM with PID 3644 (C:\Users\elisha\Desktop\spring-boot-test-0.0.1-SNAPSHOT\BOOT-INF\classes started by elisha in C:\Users\elisha\Desktop\spring-boot-test-0.0.1-SNAPSHOT)

从上面的执行接口可以看到项目引导类SpringBootTestApplication会被JarLauncher类进行引导,但是如果我们到BOOT-INF/class目录下,然后也执行java  com.spring.boot.test.SpringBootTestApplication,会报SpringApplication的ClassNotFoundException这个错误,由此可以得知这是因为java命令未指定Class Path。不过当前Spring Boot依赖的JAR文件都是存放在BOOT-INF/lib下,而org.springframework.boot.loader.JarLauncher会将JAR作为SpringBootTestApplication类库的依赖,这也就是为什么JarLauncher能引导SpringBootTestApplication,反之则是不可以的,那么对于SpringBootTestApplication是JarLauncher的子进程,还是处于同一层级呢?接下来我们来看看JarLauncher的原理。

JarLauncher实现引导原理

因为org.springframework.boot.loader.JarLauncher的类是在spring-boot-loader中,但是若想在IDEA中来看源码,需要在pom文件中引入如下配置:


  org.springframework.boot
  spring-boot-loader
  provided

在引入上面的配置文件后,便可以在IDEA中查看源码了,使用CTRL+N命令来搜索JarLauncher类,那就来看下源码,如下:

public class JarLauncher extends ExecutableArchiveLauncher {
 
 static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";
 
 static final String BOOT_INF_LIB = "BOOT-INF/lib/";
 
 public JarLauncher() {
 }
 
 protected JarLauncher(Archive archive) {
 super(archive);
 }
 
 @Override
 protected boolean isNestedArchive(Archive.Entry entry) {
 if (entry.isDirectory()) {
  return entry.getName().equals(BOOT_INF_CLASSES);
 }
 return entry.getName().startsWith(BOOT_INF_LIB);
 }
 
 public static void main(String[] args) throws Exception {
 new JarLauncher().launch(args);
 }
 
}

从上面的JarLauncher类中,可以看到两个常量:BOOT_INF_CLASSES、BOOT_INF_LIB,而它们又分别指向如下路径:BOOT-INF/classes/、BOOT-INF/lib/,并用isNestedArchive(Archive.Entry entry)方法进行判断(在Spring Boot中Archive,抽象出了Archive的概念,一个Archive可以是一个Jar(JarFileArchive)、也可以是一个目录(ExplodedArchive),在这里可以理解为Spring  Boot抽象出来的同一访问资源层。),从isNestedArchive方法的参数Archive.Entry对象貌似为一个JAR文件中的资源,譬如application.properties,同时这个对象和JarEntry是类似的,其name属性(Archive.Entry#getName())便是Jar资源的相对路径。当application.properties资源在FAT JAR目录下时,其实Archive.Entry#getName()就是/BOOT-INF/classes/application.properties,此时便符合startsWith方法的判断,所以isNestedArchive(Archive.Entry entry)便返回为true。当返回为false时,便说明FAT JAR被解压到文件目录了,由此也说明了Spring Boot应用可以通过java org.springframework.boot.loader.JarLauncher 命令启动的原因了。

Archive.Entry的实现

上面说了在Spring Boot中Archive,抽象出了Archive的概念,一个Archive可以是一个Jar(JarFileArchive)、也可以是一个目录(ExplodedArchive),这里所说的JarFileArchive、ExplodedArchive便是Archive的两种是想方式,对于这两个类的实现代码感兴趣额同学可以自己去看看。

不过由此也说明了JarLauncher  既支持JAR启动,又支持文件系统启动。同时JarLauncher 在作为引导类的时候,当执行java -jar 命令式,/META-INF/ 下MANIFEST.MF文件中的Main-Class属性将调用它的,main(String [])方法,其实它还是调用JarLauncher #launch(args)方法,这个方法是实现基类Launcher,这里简单看下这个方法的实现:

protected void launch(String[] args) throws Exception {
 JarFile.registerUrlProtocolHandler();
 ClassLoader classLoader = createClassLoader(getClassPathArchives());
 launch(args, getMainClass(), classLoader);
}

springboot是什么

springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。

上述就是小编为大家分享的怎么在Spring Boot 中启动java -jar命令了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。


分享文章:怎么在SpringBoot中启动java-jar命令
文章分享:http://scjbc.cn/article/gjjsdc.html

其他资讯