打包说明
当你执行
bash
mvn package -p dev -am xxx
会发现打出来的jar
是个压缩包。这是为什么呢?这是考虑到大多数时候标品都是作为单体项目在运行,每次打出来的包有100多M。 部署传输时,费时费力。可能有时候你就改了某个dto,service代码,便要再次传输100多M就很累,尤其是线上需要紧急修复时,便更加有体会。 基于此,实现了三方lib
包、配置分离,形成如下的目录结构:
- lib 三方包
- xxx.jar
- xxx.jar
- ...
- config 配置文件
- yml
- xml
- xxxx.jar 主包
- deploy.sh 启动脚本
在没有借助外部构建工具时,为了实现增量发布,可以手动选择要发布的jar
,配置文件等等。通过这样一种方式,便实现了增量发布。但每次手动发布还是比较麻烦。为此我们可以借助CI工具jenkins
来帮助我们快速构建。
那这个生成压缩包是如何做的呢?我们以framework-admin
模块为例讲解下。在pom.xml
里面定义了三个插件:
xml
<properties>
<scripts_bootMain>com.wmeimob.mall.web.AdminStartApplication</scripts_bootMain>
</properties>
<build>
<plugins>
<!-- 基于maven-jar-plugin插件实现把依赖jar定义写入输出jar的META-INFO/MANIFEST文件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<useUniqueVersions>false</useUniqueVersions>
<!--这里需要修改为你的项目的主启动类-->
<mainClass>${scripts_bootMain}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 拷贝项目所有依赖jar文件到构建lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
<silent>true</silent>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<!-- 打包后的包名是否包含assembly的id名 -->
<appendAssemblyId>false</appendAssemblyId>
<!-- 指定最后tar或者zip包的名字 -->
<finalName>${project.artifactId}</finalName>
<!-- tar或者zip包的输出目录 -->
<outputDirectory>target/</outputDirectory>
<descriptors>
<!-- 引用的assembly配置文件-->
<descriptor>../deploy/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<!-- phase加入package后,则在执行maven package时就可以调用maven-assembly-plugin插件定义的打包方式 -->
<execution>
<!--名字任意 -->
<id>make-assembly</id>
<!-- 绑定到package生命周期阶段上 -->
<phase>package</phase>
<goals>
<!-- 只运行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
assembly.xml 文件如下:
xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!--拷贝application.yml文件到jar包的外部config目录下面-->
<fileSet>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>application.yml</include>
<include>application-${activatedProperties}.yml</include>
<include>bootstrap.yml</include>
<include>*.xml</include>
</includes>
<filtered>true</filtered>
<outputDirectory>${project.artifactId}-${activatedProperties}/config</outputDirectory>
</fileSet>
<!--拷贝lib包到jar包的外部lib下面-->
<fileSet>
<directory>${project.build.directory}/lib</directory>
<outputDirectory>${project.artifactId}-${activatedProperties}/lib</outputDirectory>
<!-- 打包需要包含的文件 -->
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<!--启动脚本打包进zip文件-->
<fileSet>
<directory>../deploy</directory>
<outputDirectory>${project.artifactId}-${activatedProperties}/</outputDirectory>
<includes>
<include>*.sh</include>
</includes>
<!-- 文件文件权限为777 -->
<fileMode>777</fileMode>
<!-- 目录权限为777 -->
<directoryMode>777</directoryMode>
<!--脚本中参数变量为pom中的值 关键-->
<filtered>true</filtered>
</fileSet>
<!--项目编译出来的jar打包进zip文件-->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${project.artifactId}-${activatedProperties}/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
通过这么一种方式便可以实现了。
这里有个细节,zip 包里面包含一个 deploy.sh 启动脚本文件。其中
bash
#!/usr/bin/env bash
#参数值由pom文件传递
activeProfile=${activatedProperties}
baseZipName=${project.artifactId}
fileName=${project.artifactId}-${activeProfile}
jarName=${project.artifactId}
这四个变量值是动态传递进去的,在assembly.xml
文件里实现。这样的好处就是我们的服务启动名称跟着项目来走,且进行环境区分,对于在同一台部署多个服务的服务器来说,无需担心服务名会重复,只需要保证项目名称唯一即可保证服务唯一。
当然了,不生成zip
包也是可以的,注释掉pom.xml plugin
的配置,使用下面的配置即可还原成单个 jar 100M+
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>${scripts_bootMain}</mainClass>
</configuration>
</execution>
</executions>
</plugin>