spring boot项目fat jar瘦身的实现

 更新时间:2018年06月07日 13:54:21   作者:节奏35  
这篇文章主要介绍了spring boot项目fat jar瘦身的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

一、项目背景

spring cloud构建spring boot项目,精细化各项目的层次,达到降低耦合度的目的,项目间基于restful通信。

在对项目打包过程中,使用spring-boot-maven-plugin插件打包,生成的是fat jar,解压该jar包,会发现项目依赖的jar包存放于BOOT-INF下的lib文件夹中,分析多个子项目后会发现,相同的jar包占绝大多数,然后每次部署于线上环境,各系统的共同jar在服务器上其实是重复搁置的,因此自然会想到是否有方法将共同的jar包,或是不经常改动的jar包,抽离出来,整理出单独的一份,然后由各子项目启动时使用外部加载,达到fat jar瘦身的目的。

二、fat jar瘦身

经过以上分析,及查阅相关资料,整理出以下步骤进行jar包瘦身:

1.各项目配置spring-boot-maven-plugin插件(官方文档),生成fat jar中留存的jar包 

      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <layout>ZIP</layout>
          <!-- <excludeGroupIds>
            org.springframework.boot,
            org.springframework.cloud,
            org.mybatis.spring.boot,
            tk.mybatis,
            mysql,
            com.alibaba,
            javax.persistence,
            io.springfox,
            org.springframework.session
          </excludeGroupIds> -->
          <includes>
            <include>
              <groupId>xx</groupId>
              <artifactId>xx</artifactId>
            </include>
            <include>
              <groupId>xx</groupId>
              <artifactId>xx</artifactId>
            </include>
          </includes>
        </configuration>
      </plugin>

如以上代码,可以使用excludeGroupIds,或者includes,或其他标签,具体看情况。

2.在项目依赖jar中抽离出不想存放于fat jar的jar包。

方法一(推荐):在项目pom文件中添加maven依赖插件(官方文档

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.1.1</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <!-- <outputDirectory>E:/lib</outputDirectory> -->
              <excludeGroupIds>
                <!-- 留存于fat jar中的jar包的groupId属性值(多个,分隔)-->
              </excludeGroupIds>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>

标签具体含义查看官方文档。

使用maven对项目进行打包时,使用maven命令:

mvn clean install -Dmaven.test.skip=true -DoutputDirectory=E:/lib(-DoutputDirectory=E:/lib是命令动态指定项目依赖的jar包导出的路径,若在项目中指定了outputDirectory的标签值,则将覆盖此动态路径)

配置插件执行此命令后,项目中除excludeGroupIds标签中配置的jar包外,其余都将导入到指定目录中,至此完成抽离fat jar中多余的jar包。

方法二:项目中不添加maven依赖插件,直接在对项目使用mvn复制依赖jar包的命令,这种方式需要挨个对各个子项目进行依赖复制,子项目少可以使用。

mvn dependency:copy-dependencies -DoutputDirectory=E:/lib(若无动态指定目录,默认在项目的target路径下生成dependency目录)

将各项目导出的依赖jar包,统一放入一个文件夹中,去除重复,并删除fat jar中预留存的依赖jar包,至此完成抽离fat jar中多余的jar包。

3.将抽离出的jar包,放置服务器某一路径下,配置项目启动脚本,进行外部加载。

nohup java -Dloader.path="xx/lib" -jar xx.jar

-Dloader.path即外部加载地址。

至此瘦身完毕,可以在项目打包后的jar包看到,BOOT-INF下的lib中,仅有所需的jar包,大大减少了fat jar的大小。

pom的配置可以通用于微服务体系中,形成统一的配置,各个项目中的jar包依赖关系视具体情况更改。

三、遇到的问题及解决办法

在瘦身过程中,并不是一帆风顺的,当我认为大功告成,启动项目时,发现启动失败,jar冲突。

1.解决jar包冲突,通过mvn命令分析jar包的依赖关系,并找到冲突jar包,并统一版本。

在eclipse中,创建新Maven Build,一开始我尝试了mvn dependency:tree,整体分析一遍jar包依赖,但并没有找到问题jar包的依赖关系,接着我尝试了mvn dependency:tree -Dverbose,将所有间接的隐性的依赖也分析了一遍仍未找到问题jar包的依赖关系。

至此,我怀疑项目中没有这个jar包,反复打包后,我看到,此问题jar包的确在项目依赖中,只是隐藏的太深。于是,只能针对单个jar包进行分析:

mvn dependency:tree -Dverbose -Dincludes=xx:xx:xx(xx:xx:xx对应jar包的groupId:artifactId:version)

使用Dincludes后,找到了对应jar包的依赖关系,并在项目中排除了该jar包,再次打包后项目启动成功,问题解决。

2.打包过程中,一些细分的子项目,并未使用spring-boot-maven-plugin插件,而是使用maven-jar-plugin直接打包成一个可运行jar,再结合了fat jar瘦身配置后发现,原本可以依赖互通的jar,现在失效了。由于fat jar瘦身后的lib中,仅剩代码经常改动的项目的jar,依赖关系在可运行jar中,并未传递,因此需要在本项目中显性依赖所需的项目的jar包,才能保证项目的完整。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java中的动态和静态编译实例详解

    Java中的动态和静态编译实例详解

    这篇文章主要介绍了Java中的动态和静态编译实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • 详述IntelliJ IDEA提交代码前的 Code Analysis 机制(小结)

    详述IntelliJ IDEA提交代码前的 Code Analysis 机制(小结)

    本篇文章主要介绍了详述IntelliJ IDEA提交代码前的 Code Analysis 机制(小结),具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-11-11
  • 浅谈springmvc的DispatcherServlet分析

    浅谈springmvc的DispatcherServlet分析

    本篇文章主要介绍了浅谈springmvc的DispatcherServlet分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • spring boot 防止重复提交实现方法详解

    spring boot 防止重复提交实现方法详解

    这篇文章主要介绍了spring boot 防止重复提交实现方法,结合实例形式详细分析了spring boot 防止重复提交具体配置、实现方法及操作注意事项,需要的朋友可以参考下
    2019-11-11
  • 使用Java实现价格加密与优化功能

    使用Java实现价格加密与优化功能

    在现代软件开发中,数据加密是一个非常重要的环节,尤其是在处理敏感信息(如价格、用户数据等)时,本文将详细介绍如何使用 Java 实现价格加密,并对代码进行优化,需要的朋友可以参考下
    2025-01-01
  • Java使用EasyExcel实现高效的Excel读写操作

    Java使用EasyExcel实现高效的Excel读写操作

    在日常开发中,Excel 文件的读写操作是一个常见的需求,EasyExcel 是阿里巴巴开源的一个高性能、易用的 Excel 读写库,可以大幅提高处理 Excel 文件的效率,本篇博客将从 EasyExcel 的基本概念、优势、安装、读写操作以及高级用法展开,需要的朋友可以参考下
    2024-12-12
  • Java对象序列化操作详解

    Java对象序列化操作详解

    这篇文章主要介绍了Java对象序列化操作,简单描述了Java序列化相关概念、原理并结合实例形式总结分析了常见序列化操作相关定于与使用技巧,需要的朋友可以参考下
    2018-09-09
  • IDEA项目maven project没有出现plugins和Dependencies问题

    IDEA项目maven project没有出现plugins和Dependencies问题

    这篇文章主要介绍了IDEA项目maven project没有出现plugins和Dependencies问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Spring中的BeanFactory与FactoryBean区别详解

    Spring中的BeanFactory与FactoryBean区别详解

    这篇文章主要介绍了Spring中的BeanFactory与FactoryBean区别详解,BeanFactory是一个接口,它是spring中的一个工厂,FactoryBean也是一个接口,实现了3个方法,通过重写其中方法自定义生成bean,需要的朋友可以参考下
    2024-01-01
  • JavaWeb.servlet的基本使用方法详解

    JavaWeb.servlet的基本使用方法详解

    Servlet指在服务器端执行的一段Java代码,可以接收用户的请求和返回给用户响应结果,下面这篇文章主要给大家介绍了关于JavaWeb.servlet基本使用的相关资料,需要的朋友可以参考下
    2022-04-04

最新评论