SpringBoot-Maven打包压缩瘦身

SpringBoot-Maven打包压缩瘦身

  • 一、Spring Boot 可执行 jar 分析
    • 1.1 打包
    • 1.2 两种 jar 的比较
    • 1.3 一次打包两个 jar
  • 二、SpringBoot迭代发布JAR瘦身配置
  • 三、引入内部编译的依赖
    • 3.1 剔除不需要的依赖
      • 3.1.1 方式一:排除一个具体的maven 模块,通过唯一的groupId和artifactId组合来实现。(如果有必要,可以加入classifier来唯一确认。)
      • 3.1.2 方式二:排除和“指定的artifactId”相符的所有maven模块
      • 3.1.3 方式三:排除属于“指定的groupId”的所有maven模块
  • 四、Spring Boot Thin Launcher
  • 五、 maven的assembly打包插件
  • 六、SpringBoot剔除静态文件
    • 6.1 打包时排除resources下的资源文件



相关内容原文地址:

腾讯云:江南一点雨:Spring Boot2 系列教程(四十)Spring Boot 可执行 jar 分析
脚本之家:田心双木:详解SpringBoot迭代发布JAR瘦身配置
CSDN:希尔伯特:SpringBoot瘦身打包部署
简书:思_路:Springboot 打包瘦身
张扎瓦的博客:springboot将项目与依赖分开打包
柒’s Blog:SpringBoot 2.0 开发案例之百倍级减肥瘦身之旅
周钦雄:Spring cloud的Maven插件(一):repackage目标



一、Spring Boot 可执行 jar 分析

Spring Boot 中默认打包成的 jar 叫做 可执行 jar,这种 jar 不同于普通的 jar,普通的 jar 不可以通过 java -jar xxx.jar 命令执行,普通的 jar 主要是被其他应用依赖,Spring Boot 打成的 jar 可以执行,但是不可以被其他的应用所依赖,即使强制依赖,也无法获取里边的类。但是可执行 jar 并不是 Spring Boot 独有的,Java 工程本身就可以打包成可执行 jar 。

Spring Boot 项目中一个默认的插件配置 spring-boot-maven-plugin ,这个打包插件存在 5 个方面的功能,从插件命令就可以看出:
SpringBoot-Maven打包压缩瘦身_第1张图片
五个功能分别是:

  1. build-info:生成项目的构建信息文件 build-info.properties
  2. repackage:这个是默认 goal,在 mvn package 执行之后,这个命令再次打包生成可执行的 jar,同时将 mvn package 生成的 jar 重命名为 *.origin
  3. run:这个可以用来运行 Spring Boot 应用
  4. start:这个在 mvn integration-test 阶段,进行 Spring Boot 应用生命周期的管理
  5. stop:这个在 mvn integration-test 阶段,进行 Spring Boot 应用生命周期的管理

这里功能,默认情况下使用就是 repackage 功能,其他功能要使用,则需要开发者显式配置。

1.1 打包

repackage 功能的 作用,就是在打包的时候,多做一点额外的事情:

  1. 首先 mvn package 命令 对项目进行打包,打成一个 jar,这个 jar 就是一个普通的 jar,可以被其他项目依赖,但是不可以被执行。
  2. repackage 命令,对第一步 打包成的 jar 进行再次打包,将之打成一个 可执行 jar ,通过将第一步打成的 jar 重命名为 *.original 文件

举个例子:

对任意一个 Spring Boot 项目进行打包,可以执行 mvn package 命令,也可以直接在 IDEA 中点击 package ,如下 :
SpringBoot-Maven打包压缩瘦身_第2张图片
打包成功之后, target 中的文件如下:
SpringBoot-Maven打包压缩瘦身_第3张图片
这里有两个文件,第一个 restful-0.0.1-SNAPSHOT.jar 表示打包成的可执行 jar ,第二个 restful-0.0.1-SNAPSHOT.jar.original 则是在打包过程中 ,被重命名的 jar,这是一个不可执行 jar,但是可以被其他项目依赖的 jar。

1.2 两种 jar 的比较

可执行 jar 解压之后,目录如下:
SpringBoot-Maven打包压缩瘦身_第4张图片
可执行 jar 中,我们自己的代码是存在 于 BOOT-INF/classes/ 目录下,另外,还有一个 META-INF 的目录,该目录下有一个 MANIFEST.MF 文件,打开该文件,内容如下:

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

可以看到,这里定义了一个 Start-Class,这就是可执行 jar 的入口类,Spring-Boot-Classes 表示我们自己代码编译后的位置,Spring-Boot-Lib 则表示项目依赖的 jar 的位置。

换句话说,如果自己要打一个可执行 jar 包的话,除了添加相关依赖之外,还需要配置 META-INF/MANIFEST.MF 文件。

这是可执行 jar 的结构,那么不可执行 jar 的结构呢?

首先将默认的后缀 .original 除去,然后给文件重命名,重命名完成,进行解压:
SpringBoot-Maven打包压缩瘦身_第5张图片
解压后可以看到,不可执行 jar 根目录就相当于我们的 classpath,解压之后,直接就能看到我们的代码,它也有 META-INF/MANIFEST.MF 文件,但是文件中没有定义启动类等。

Manifest-Version: 1.0
Implementation-Title: restful
Implementation-Version: 0.0.1-SNAPSHOT
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0

注意

不可以执行 jar 也没有将项目的依赖打包进来。

从这里我们就可以看出,两个 jar ,虽然都是 jar 包,但是内部结构是完全不同的,因此一个可以直接执行,另一个则可以被其他项目依赖。

1.3 一次打包两个 jar

一般来说,Spring Boot 直接打包成可执行 jar 就可以了,不建议将 Spring Boot 作为普通的 jar 被其他的项目所依赖。如果有这种需求,建议将被依赖的部分,单独抽出来做一个普通的 Maven 项目,然后在 Spring Boot 中引用这个 Maven 项目。

如果非要将 Spring Boot 打包成一个普通 jar 被其他项目依赖,技术上来说,也是可以的,给 spring-boot-maven-plugin 插件添加如下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
            <configuration>
                <classifier>execclassifier>
            configuration>
        plugin>
    plugins>
build>

配置的 classifier 表示可执行 jar 的名字,配置了这个之后,在插件执行 repackage 命令时,就不会给 mvn package 所打成的 jar 重命名了,所以,打包后的 jar 如下:
在这里插入图片描述
第一个 jar 表示可以被其他项目依赖的 jar ,第二个 jar 则表示一个可执行 jar。

二、SpringBoot迭代发布JAR瘦身配置

默认情况下,插件 spring-boot-maven-plugin 会把整个项目打包成一个可运行的Jar包(即所谓的Flat Jar),导致了这个Jar包很大(通常有几十M+)。

把第三方的JAR与项目代码分离,第三方的JAR把移除到lib文件夹中,即可实现为我们的可执行JAR瘦身,配置如下:

<plugins>
  
  <plugin>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-maven-pluginartifactId>
    <configuration>
      
      <mainClass>com.bdfint.logistics.app.driver.LogisticsAppDriverApplicationmainClass>
      
      <layout>ZIPlayout>
      
      <includes>
        
        
          
          
        
        <include>
          <groupId>com.bdfint.logisticsgroupId>
          <artifactId>logistics-apiartifactId>
        include>
        <include>
          <groupId>com.bdfint.logisticsgroupId>
          <artifactId>logistics-commonartifactId>
        include>
      includes>
    configuration>
    <executions>
      <execution>
        <goals>
          <goal>repackagegoal>
        goals>
      execution>
    executions>
  plugin>
  
  <plugin>
    <groupId>org.apache.maven.pluginsgroupId>
    <artifactId>maven-dependency-pluginartifactId>
    <executions>
      <execution>
        <id>copy-dependenciesid>
        <phase>prepare-packagephase>
        <goals>
          <goal>copy-dependenciesgoal>
        goals>
        <configuration>
          <outputDirectory>${project.build.directory}/liboutputDirectory>
          
          <excludeGroupIds>
            com.bdfint.logistics
          excludeGroupIds>
        configuration>
      execution>
    executions>
  plugin>
plugins>

接下来,执行打包命令:mvn clean package -Dmaven.test.skip=true,打包后在target目录下就包含我们的JAR和lib目录,如下图:
SpringBoot-Maven打包压缩瘦身_第6张图片
CMD定位到target目录下,执行命令:java -Dloader.path=./lib -jar logistics-app-driver-2.9.1.1.jar,即可把项目JAR跑起来!

三、引入内部编译的依赖

如果想引入内部编译的依赖包可以通过includes属性进行添加,利用引用了内部的dubbo可以通过如下配置:
SpringBoot-Maven打包压缩瘦身_第7张图片
配置完成后,再次执行编译:mvn clean package。

如果引入内部包过多,也可以通过excludeGroupIds属性去掉不变的依赖包。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
            <configuration>
              <layout>ZIPlayout>
                    
                    <excludeGroupIds>
                         org.springframework.boot,
                         org.springframework,
                         org.springframework.data,
                         org.apache.tomcat.embed
                   excludeGroupIds>
             configuration>     
        plugin>
    plugins>
build>   

注:layout 必须是 ZIP 、 excludeGroupIds 中时忽略也是就需要打在外部的 jar。

3.1 剔除不需要的依赖

3.1.1 方式一:排除一个具体的maven 模块,通过唯一的groupId和artifactId组合来实现。(如果有必要,可以加入classifier来唯一确认。)

 1 <project>
 2   ...
 3   <build>
 4     ...
 5     <plugins>
 6       ...
 7       <plugin>
 8         <groupId>org.springframework.bootgroupId>
 9         <artifactId>spring-boot-maven-pluginartifactId>
10         <version>1.5.6.RELEASEversion>
11         <configuration>
12           <excludes>
13             <exclude>
14               <groupId>com.foogroupId>
15               <artifactId>barartifactId>
16             exclude>
17           excludes>
18         configuration>
19         ...
20       plugin>
21       ...
22     plugins>
23     ...
24   build>
25   ...
26 project>

3.1.2 方式二:排除和“指定的artifactId”相符的所有maven模块

 1 <project>
 2   ...
 3   <build>
 4     ...
 5     <plugins>
 6       ...
 7       <plugin>
 8         <groupId>org.springframework.bootgroupId>
 9         <artifactId>spring-boot-maven-pluginartifactId>
10         <version>1.5.6.RELEASEversion>
11         <configuration>
12           <excludeArtifactIds>my-lib,another-libexcludeArtifactIds>
13         configuration>
14         ...
15       plugin>
16       ...
17     plugins>
18     ...
19   build>
20   ...
21 project>

3.1.3 方式三:排除属于“指定的groupId”的所有maven模块

 1 <project>
 2   ...
 3   <build>
 4     ...
 5     <plugins>
 6       ...
 7       <plugin>
 8         <groupId>org.springframework.bootgroupId>
 9         <artifactId>spring-boot-maven-pluginartifactId>
10         <version>1.5.6.RELEASEversion>
11         <configuration>
12           <excludeGroupIds>com.fooexcludeGroupIds>
13         configuration>
14         ...
15       plugin>
16       ...
17     plugins>
18     ...
19   build>
20   ...
21 project>

四、Spring Boot Thin Launcher

使用插件以后,原来打包45M的jar包,现在体积只有 40K,瘦身效果非常明显,并且也不改变原有的打包方式和部署方法。打包以后的jar也是可执行的。

第一次执行时,会自动下载所有的依赖包,并且缓存到本地,默认的缓存路径是${user.home}/.m2/,你也可以使用如下命令在启动时修改依赖的路径

java -Dthin.root=.  -jar  app-0.0.1-SNAPSHOT.jar

在pom.xml添加以下插件代码,然后正常地打包即可:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot.experimentalgroupId>
                    <artifactId>spring-boot-thin-layoutartifactId>
                    <version>1.0.3.RELEASEversion>
                dependency>
            dependencies>
            <configuration>
                <executable>trueexecutable>
            configuration>
        plugin>
    plugins>
build>

五、 maven的assembly打包插件

assembly配置:
在项目中创建一个文件,放在src/main/assembly/assembly.xml中。
SpringBoot-Maven打包压缩瘦身_第8张图片
assembly中的具体配置:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

    
    <id>binid>

    
    <formats>
        <format>zipformat>
    formats>

    
    <includeBaseDirectory>falseincludeBaseDirectory>

    <dependencySets>
        <dependencySet>
            
            <useProjectArtifact>falseuseProjectArtifact>
            <outputDirectory>liboutputDirectory>
            <unpack>falseunpack>
        dependencySet>
    dependencySets>

    <fileSets>
        
        <fileSet>
            <directory>${project.basedir}directory>
            <outputDirectory>outputDirectory>
            <includes>
                <include>README*include>
                <include>LICENSE*include>
                <include>NOTICE*include>
            includes>
        fileSet>

        
        <fileSet>
            <directory>${project.basedir}/src/main/resourcesdirectory>
            <outputDirectory>configoutputDirectory>
        fileSet>

        
        <fileSet>
            <directory>${project.basedir}/src/main/bindirectory>
            <outputDirectory>binoutputDirectory>
        fileSet>

        
        <fileSet>
            <directory>${project.build.directory}directory>
            <outputDirectory>outputDirectory>
            <includes>
                <include>*.jarinclude>
            includes>
        fileSet>
    fileSets>
assembly>

maven中的配置:

<build>
    <plugins>
        
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-jar-pluginartifactId>
            <configuration>
                <archive>
                    
                    <addMavenDescriptor>falseaddMavenDescriptor>
                    <manifest>
                        
                        <addClasspath>trueaddClasspath>
                        
                        <classpathPrefix>lib/classpathPrefix>
                        
                        <mainClass>com.zbrx.speed.AppmainClass>
                    manifest>
                archive>
            configuration>
        plugin>

        
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-assembly-pluginartifactId>
            <configuration>
                <descriptors>
                    
                    <descriptor>src/main/assembly/assembly.xmldescriptor>
                descriptors>
            configuration>
            <executions>
                <execution>
                    <id>make-assemblyid>
                    <phase>packagephase>
                    <goals>
                        <goal>singlegoal>
                    goals>
                execution>
            executions>
        plugin>


        
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-surefire-pluginartifactId>
            <configuration>
                <skipTests>trueskipTests>
            configuration>
        plugin>
    plugins>
build>

最终打包后的效果:
SpringBoot-Maven打包压缩瘦身_第9张图片
压缩包里的文件内容:
SpringBoot-Maven打包压缩瘦身_第10张图片
config配置文件:
SpringBoot-Maven打包压缩瘦身_第11张图片

六、SpringBoot剔除静态文件

静态文件排除到项目外面,pom.xml 继续引入:

<resources>
     <resource>
       <filtering>truefiltering>
       <directory>src/main/resourcesdirectory>
       <excludes>
         <exclude>static/**exclude>
       excludes>
     resource>
resources>

配置nginx,访问静态资源文件:

server {
        listen       80;
        server_name  www.cloudbed.vip;
        location / {
            proxy_pass http://127.0.0.1:8080;
        }
        #静态文件交给nginx处理
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ioc|rar|
            zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
        {
            root /cloudbed/static;
            expires 30d;
        }
        location ~ .*\.(js|css)?$
        {
            root /cloudbed/static;
            expires 1h;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}

6.1 打包时排除resources下的资源文件

 1 <build>
 2   ...
 3     <resources>
 4         <resource>
 5             <directory>src/main/resourcesdirectory>
 6             <excludes>
 7                 <exclude>**/*.propertiesexclude>
 8                 <exclude>**/*.xmlexclude>
 9                 <exclude>**/*.ymlexclude>
10             excludes>
11         resource>
12     resources>
13     <plugins>
14       ...
15         <plugin>
16             <groupId>org.springframework.bootgroupId>
17             <artifactId>spring-boot-maven-pluginartifactId>
18             <executions>
19                 <execution>
20                     <goals>
21                         <goal>repackagegoal>
22                     goals>
23                 execution>
24             executions>
25         plugin>
26       ...
27     plugins>
28   ...
29 build>

你可能感兴趣的:(Spring,Boot,全家桶,▷微服务框架,▷Java程序开发)