SpringBoot jar包太大的问题

分享  收藏
0 / 3066

Spring boot 添加 spring-boot-maven-plugin 插件后, 打出来的 Jar 动辄几十上百兆。 这种 FatJar 包在传输时会相当不便, 尤其是某些外企, 服务器可能在美国, 上传速度可能不到 200K, 严重影响工作效率。

本文就说说怎样减少 FatJar 的大小。

SpringBoot 的 Web 应用一般都添加了 spring-boot-maven-plugin 插件。

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

打出来的 jar 包内置了所有的依赖 jar, 放在 BOOT-INF/lib 目录, 所以体积很大。

解决步骤:

  1. 修改 spring-boot-maven-plugin 的参数, 使其将内置的 jar 包 exclude 掉, 例如: <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.5.1.RELEASE</version> <configuration> <layout>ZIP</layout> <excludes> <exclude> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclude> <exclude> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclude> </excludes> </configuration> </plugin>

这样, 打出来的 jar 中就不会包含被 exclude 掉的依赖了。注意 layout 应设置为 ZIP,不然后面会出现找不到类的错误。

exclude 不止一种写法, 其他的 exclude 方式参见 http://docs.spring.io/spring-boot/docs/current/maven-plugin/start-mojo.html.

可以通过 mvn dependency:tree 命令查看当前项目的依赖。

因为依赖的 jar 已经被排除掉了, FatJar 变瘦, 直接运行就会报 ClassNotFoundException. 所以还要进行下一步。

可以在公司的 parent pom.xml 的 pluginManagement 部分添加 spring-boot-maven-plugin 的配置, 这样每个 Web 项目就可以继承一套全公司统一的配置。

2.将上一步 exclude 掉的 jar 放到一个外置的目录中。 如

在这里插入图片描述

然后执行如下命令启动应用:

Cmd 代码

java -Dloader.path="lib/" -jar common-service.jar  
或
后台启动
nohup java -jar 自己的springboot项目.jar >日志文件名.log 2>&1 &


命令详解:

nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。

>日志文件名.log:是nohup把command的输出重定向到当前目录的指定的“日志文件名.log”文件中,即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。不指定文件名会在当前目录创建nohup.out,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。


2>&1:2就是标准错误,1是标准输出,该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。


java -jar 自己的springboot项目.jar:执行springboot的项目,如果单单只执行该命令,linux只会短暂的运行该项目,当退出控制台后会自动关闭该项目。


最后的&:让作业在后台运行。

loader.path 指向了外置目录,告诉 SpringBoot 允许从外部加载依赖。

loader.path 的更多用法参见:http://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#executable-jar-launching.

可以用 mvn dependency:copy-dependencies 命令将 jar 包 copy 到这个外置目录。

经测试, 经过上面的两个步骤, 笔者的应用从 70MB 缩小为 1.3MB, 极大地缩小了体积。

既缩小了体积, 便于传输, 又很容易地控制依赖 jar 的版本, 做到全公司统一, 共享同一套依赖集合。

特别地, 如果要讲应用部署到 docker 中, 需要修改 dockerfile, 将依赖目录挂载到 docker 镜像中, 修改应用的启动命令(可能会是 dockerfile 的 entrypoint),添加 loader.path 参数, 指向挂载进来的依赖目录。 不建议将依赖 ADD 到 docker 镜像, 那样的话 docker 镜像会很大。