写点什么

springboot 项目打包优化(核心 class 与依赖 jar 分离)

作者:安逸的咸鱼
  • 2022 年 7 月 22 日
  • 本文字数:2505 字

    阅读完需:约 8 分钟

之所以研究 SpringBoot 项目的打包优化,是最近在学习 SpringCloud 微服务,写了一个仅提供 eureka 注册服务中的功能的 springboot 项目,打包后 50M,一考虑到实际上或许会部署多个应用到同一台服务器,那里面重复 jar 包就很占很大一部分

在日常工作里,仅仅修复了一个 bug,改动了几个文件,就得重新打包,然后走向日葵给现场提供一个近 100M 的包,文件传输的速度实在是太拉垮了

项目环境

maven:    3.5.9springboot:  2.3.8.RELEASEjava:    1.8
复制代码

方案 1

打包插件 spring-boot-maven-plugin

通过 spring starter project 创建项目时会默认带有这个插件,并且会自动排除 lombok 的依赖,我们需要做的就是添加其他配置


<plugin>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-maven-plugin</artifactId>  <configuration>    <!-- 指定该Main Class为全局的唯一入口 -->    <mainClass>com.wx.demo.EurekaServiceApplication</mainClass>    <!--把第三方jar包打入jar -->    <includeSystemScope>true</includeSystemScope>    <fork>true</fork>    <!-- 设置为ZIP,此模式下spring-boot-maven-plugin会将Manifest.MF文件中的Main-Class设置为org.springframework.boot.loader.PropertiesLauncher -->    <layout>ZIP</layout>    <includes>      <!--去除在生产环境中不变的依赖 -->      <!--<excludeGroupIds> -->      <!--org.springframework.boot -->      <!--</excludeGroupIds> -->      <include>        <!-- 排除所有Jar -->        <groupId>nothing</groupId>        <artifactId>nothing</artifactId>      </include>    </includes>  </configuration>  <executions>    <execution>      <goals>        <goal>repackage</goal>        <!--可以把依赖的包都打包到生成的Jar包中 -->      </goals>    </execution>  </executions></plugin>
复制代码

依赖相关的处理插件 maven-dependency-plugin

添加插件 ,用途为将项目中用到的 jar 包,复制到指定的路径


<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-dependency-plugin</artifactId>  <executions>    <execution>      <id>copy</id>      <phase>package</phase>      <goals>        <goal>copy-dependencies</goal>      </goals>      <configuration>        <!-- 将 jar 包复制到 mvn 项目的构建路径下,例如 项目名/target/libs/ 目录下-->        <!-- <outputDirectory>${project.build.directory}/libs</outputDirectory> -->        <!-- 将 jar 放到固定的位置,方便管理 -->        <outputDirectory>C:/Users/wangbin1/Desktop/libs</outputDirectory>      </configuration>    </execution>  </executions></plugin>
复制代码

测试插件 maven-surefire-plugin

maven-surefire-plugin是 maven 里执行测试用例的插件,不显示配置就会用默认配置。这个插件的surefire:test命令会默认绑定 maven 执行的test阶段。


<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-surefire-plugin</artifactId>  <configuration>    <!-- 跳过打包单元测试 -->    <skipTests>true</skipTests>  </configuration></plugin>
复制代码


缺点:在运行 jar 包的时候,我们需要额外指定运行参数 -Dloader.path=libs/,就是告诉虚拟机需要去哪里加载项目中关联的 jar

方案 2

二号打包插件 maven-jar-plugin

替换插件 spring-boot-maven-plugin,在插件里指明 jar 包运行时需要去哪里加载依赖的 jar


<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-jar-plugin</artifactId>  <configuration>    <archive>      <manifest>        <addClasspath>true</addClasspath>        <!-- 运行时需要额外加载读取 jar 包的位置 -->        <classpathPrefix>libs/</classpathPrefix>        <mainClass>com.wx.demo.EurekaServiceApplication</mainClass>      </manifest>    </archive>  </configuration></plugin>
复制代码


如代码中配置的路径为 libs/,这是一个相对路径,后续我们运行 eureka.jar 包时,就需要将 eureka.jar 和 libs/ 放在同级目录下


|- libs  |- a.jar  |- b.jar  |- xxx|- eureka.jar
复制代码




或者,将 libs 包放到 jdk 环境下,如我本机的 jdk 路径为 C:\Program Files\Java\jdk1.8.0_181


注意点:在打包插件中,<classpathPrefix> 配置的是相对路径,在依赖管理的插件中,<outputDirectory> 配置的是绝对路径


更新

在实际使用的过程中,发现需要对打包的应用进行名称指定


如果是使用 spring-boot-maven-plugin,可以通过configuration.finalName 来指定,但是因为需要使用maven-jar-plugin 进行打包,查阅后发现有提供相关配置项configuration.archive.manifest.packageName,遗憾的是打包的文件名还是默认值


最后的解决方案就是,使用 pom 文件的节点参数配置 build.finalName,成功

后续

因为是在学习微服务,将 注册中心,生产者,消费者 3 个 springboot 项目打包后,需要通过 cmd 运行起来,每次都手动新开 cmd 就很麻烦,网上查找到相关资料

在当前 cmd 中新开一个 cmd 命令行

start cmd
复制代码

新开一个 cmd 命令行,并执行一条命令

start cmd /k java -jar eureka-service-0.0.1.jar
复制代码

/k 和 /C 的区别

/k 命令执行完后,窗口不会关闭/C 命令执行完后,窗口会关闭
复制代码

新开命令行,并在后台执行命令,将运行的数据输出到指定文件

执行一条命令,并将执行的结果输出到指定路径的文件中


覆盖写入 > filepath


追加写入 >> filepath


> filepathh 2>&1,2>&1,错误定向到输出,标准输入又追加到 file 中,所以错误和 cmd 输出都追加到 file


cmd /c start /b java -jar > "d:/log/autopack/网页程序运行监控.log" 2>&1 "AutoPackageLine-1.jar"
复制代码

关闭指定的进程

/T                     终止指定的进程和由它启用的子进程。/F                     指定强制终止进程。/IM   imagename        指定要终止的进程的映像名称。通配符 '*'可用来示例代码,关闭全部的 java 进程taskkill -t -f  /im java
复制代码


发布于: 刚刚阅读数: 6
用户头像

CV 工程师 2022.07.13 加入

还未添加个人简介

评论

发布
暂无评论
springboot 项目打包优化(核心 class 与依赖 jar 分离)_Java_安逸的咸鱼_InfoQ写作社区