Springboot thin jar启动失败问题处理

1,149 阅读1分钟

springboot thin jar启动失败处理

起因

使用springboot开发java后端服务很方便,但是久而久之发现springboot的依赖也越来越多jar也越来越大,有时候构建项目部署也很慢,针对这个问题springboot也给出给jar“瘦身”的方法,就是使用spring-boot-thin-launcher使用方式也很简单。只要在spring-boot-maven-plugin插件中引入 spring-boot-thin-layout就可以。

<properties>
    <wrapper.version>1.0.27.RELEASE</wrapper.version>
</properties>

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot.experimental</groupId>
            <artifactId>spring-boot-thin-layout</artifactId>
            <version>${wrapper.version}</version>
	</dependency>
    </dependencies>
 </plugin>

分析问题

在项目中引入spring-boot-thin-layout之后,通过mvn package构建jar构建完成之后发现jar变小了只有几十kb,这是因为通过thin瘦身之后,构建的jar包只包含我们的类,没有其他东西。

 troyMac~ ll ./target
total 48
drwxr-xr-x  4 qujianfei  staff   128B  3 30 23:12 classes
-rw-r--r--  1 qujianfei  staff    14K  3 30 23:12 function-sample-pojo-2.0.0.RELEASE.jar
-rw-r--r--  1 qujianfei  staff   6.5K  3 30 23:12 function-sample-pojo-2.0.0.RELEASE.jar.original

但是如果这时候我们直接通过jar -jar来运行应用,会遇到class not found的异常服务无法启动,原因就是上面说到的因为这个thin jar只有我们自己的类,没有服务所需要的依赖等其他信息因此无法启动。

Exception in thread "main" java.lang.ClassNotFoundException: org.springframework.boot.loader.thin.ThinJarLauncher
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.springframework.boot.loader.wrapper.ThinJarWrapper.launch(ThinJarWrapper.java:138)
	at org.springframework.boot.loader.wrapper.ThinJarWrapper.main(ThinJarWrapper.java:107)

针对这个问题也找了一些资料,说是通过指定-Dthin.root=.,这个方式我尝试了还是不行。因为-Dthin.root参数是指定一个本地的依赖缓存的位置,可以理解为maven仓库,如果目录不存在就会创建一个。可以问题的关键是依赖没有被下载下来。

解决问题 - 使用spring-boot-thin-maven-plugin

后来发现解决这个问题可以选择添加spring-boot-thin-maven-plugin,然后重新执行mvn package,这时候会在target目录下多一个thin的目录,./target/thin目录下会保存应用所需要的依赖,这时候在启动服务,通过java -Dthin.root=target/thin/root -jar ./target/function-sample-pojo-2.0.0.RELEASE.jar参数指定依赖所需再的仓库位置repository服务就可以正常启动。

    <plugin>
        <groupId>org.springframework.boot.experimental</groupId>
        <artifactId>spring-boot-thin-maven-plugin</artifactId>
        <version>${wrapper.version}</version>
        <executions>
            <execution>
                <!-- Download the dependencies at build time -->
                <id>resolve</id>
                <goals>
                    <goal>resolve</goal>
                </goals>
                <inherited>false</inherited>
            </execution>
        </executions>
    </plugin>

./target/thin目录 image.png 服务启动正常 image.png

总结

在使用spring-boot-thin-layout构建thin jar,在启动的时候如果遇到Exception in thread "main" java.lang.ClassNotFoundException: org.springframework.boot.loader.thin.ThinJarLauncher异常,可以使用spring-boot-thin-maven-plugin将依赖拉取到本地,再结合-Dthin.root参数来解决。

pom.xml中的plugins

<plugins>
    <plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<dependencies>
            <dependency>
                 <groupId>org.springframework.boot.experimental</groupId>
		<artifactId>spring-boot-thin-layout</artifactId>
		<version>${wrapper.version}</version>
            </dependency>
	</dependencies>
    </plugin>

    <plugin>
        <groupId>org.springframework.boot.experimental</groupId>
        <artifactId>spring-boot-thin-maven-plugin</artifactId>
        <version>${wrapper.version}</version>
        <executions>
            <execution>
                <!-- Download the dependencies at build time -->
                <id>resolve</id>
                <goals>
                    <goal>resolve</goal>
                </goals>
                <inherited>false</inherited>
            </execution>
        </executions>
    </plugin>
</plugins>