Apache Maven Assembly自定义打包插件的使用
前言
- 本文主要记录在SpringBoot项目中使用Apache Maven Assembly插件进行打包的相关内容;
- 官网说明:https://maven.apache.org/plugins/maven-assembly-plugin/
概述
- 是什么:Apache Maven Assembly是Maven的程序集插件使开发人员能够将项目输出合并到单个可分发的存档中,该存档还包含依赖项、模块、站点文档和其他文件。
- 作用:可以实现自定义打包,从而实现打包项目可以外挂yml配置文件,提供shell运维脚本,大大降低运维成本,比较适用于小规模的SpringBoot项目(大规模的项目推荐docker容器部署)
配置说明
引入插件(pom文件中)
<?xml version="1.0" encoding="UTF-8"?>
<project>
...
<build>
<plugins>
<!--springboot项目打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.alan.SpringBootMain</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!--maven自定义打包插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<descriptors>
<!--具体的配置文件-->
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!--绑定到maven操作类型上-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
配置assembly文件(在pom中设定的位置下创建,我这里是src/main/assembly/assembly.xml)
<assembly>
<!--
必须写,否则打包时会有 assembly ID must be present and non-empty 错误
这个名字最终会追加到打包的名字的末尾,如项目的名字为 hangge-test-0.0.1-SNAPSHOT,
则最终生成的包名为 hangge-test-0.0.1-SNAPSHOT-bin.tar.gz
-->
<id>bin</id>
<!-- 打包的类型,如果有N个,将会打N个类型的包 -->
<formats>
<format>tar.gz</format>
<!--<format>zip</format>-->
</formats>
<includeBaseDirectory>true</includeBaseDirectory> <!--第三方依赖设置-->
<dependencySets>
<dependencySet>
<!--使用项目中的artifact,第三方包打包进tar.gz文件的lib目录下-->
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
<!--文件设置-->
<fileSets>
<!--
0755->即用户具有读/写/执行权限,组用户和其它用户具有读写权限;
0644->即用户具有读写权限,组用户和其它用户具有只读权限;
-->
<!-- 将src/main/assembly/bin目录下的所有文件输出到打包后的bin目录中 -->
<fileSet>
<directory>src/main/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
<!--如果是脚本,一定要改为unix.如果是在windows上面编码,会出现dos编写问题-->
<lineEnding>unix</lineEnding>
<filtered>true</filtered><!-- 是否进行属性替换 -->
</fileSet>
<!-- 将src/main/assembly/config目录下的所有文件输出到打包后的config目录中 -->
<fileSet>
<directory>src/main/assembly/config</directory>
<outputDirectory>config</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<!-- 将src/main/resources下配置文件打包到config目录 -->
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>/config</outputDirectory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.yml</include>
</includes>
<filtered>true</filtered><!-- 是否进行属性替换 -->
</fileSet>
<!-- 将项目启动jar打包到lib目录中 -->
<fileSet>
<directory>target</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<!-- 将项目说明文档打包到docs目录中 -->
<fileSet>
<directory>.</directory>
<outputDirectory>docs</outputDirectory>
<includes>
<include>*.md</include>
</includes>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>docs</directory>
<outputDirectory>docs</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>src/main/assembly/docs</directory>
<outputDirectory>docs</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
</assembly>
编写运维shell脚本(在assembly中设定的位置下创建,我这里是src/main/assembly/bin)
- start.sh
#!/bin/bash
# 项目名称
SERVER_NAME="${project.artifactId}" # jar名称
JAR_NAME="${project.build.finalName}.jar" # 进入bin目录
cd `dirname $0`
# bin目录绝对路径
BIN_DIR=`pwd`
# 返回到上一级项目根目录路径
cd ..
# 打印项目根目录绝对路径
# `pwd` 执行系统命令并获得结果
DEPLOY_DIR=`pwd` # 外部配置文件绝对目录,如果是目录需要/结尾,也可以直接指定文件
# 如果指定的是目录,spring则会读取目录中的所有配置文件
CONF_DIR=$DEPLOY_DIR/config
# SERVER_PORT=`sed '/server.port/!d;s/.*=//' config/application.properties | tr -d '\r'`
# 获取应用的端口号
SERVER_PORT=`sed -nr '/port: [0-9]+/ s/.*port: +([0-9]+).*/\1/p' config/application.yml` PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'`
if [ "$1" = "status" ]; then
if [ -n "$PIDS" ]; then
echo "The $SERVER_NAME is running...!"
echo "PID: $PIDS"
exit 0
else
echo "The $SERVER_NAME is stopped"
exit 0
fi
fi if [ -n "$PIDS" ]; then
echo "ERROR: The $SERVER_NAME already started!"
echo "PID: $PIDS"
exit 1
fi if [ -n "$SERVER_PORT" ]; then
SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PORT | wc -l`
if [ $SERVER_PORT_COUNT -gt 0 ]; then
echo "ERROR: The $SERVER_NAME port $SERVER_PORT already used!"
exit 1
fi
fi # 项目日志输出绝对路径
LOGS_DIR=$DEPLOY_DIR/logs
# 如果logs文件夹不存在,则创建文件夹
if [ ! -d $LOGS_DIR ]; then
mkdir $LOGS_DIR
fi
STDOUT_FILE=$LOGS_DIR/catalina.log # JVM Configuration
JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
JAVA_DEBUG_OPTS=""
if [ "$1" = "debug" ]; then
JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
fi JAVA_JMX_OPTS=""
if [ "$1" = "jmx" ]; then
JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false "
fi JAVA_MEM_OPTS=""
BITS=`java -version 2>&1 | grep -i 64-bit`
if [ -n "$BITS" ]; then
JAVA_MEM_OPTS=" -server -Xmx512m -Xms512m -XX:PermSize=128m -XX:+UseG1GC "
else
JAVA_MEM_OPTS=" -server -Xms512m -Xmx512m -XX:PermSize=128m -XX:+UseParallelGC "
fi # 加载外部log4j2文件的配置
LOG_IMPL_FILE=log4j2.xml
LOGGING_CONFIG=""
if [ -f "$CONF_DIR/$LOG_IMPL_FILE" ]
then
LOGGING_CONFIG="-Dlogging.config=$CONF_DIR/$LOG_IMPL_FILE"
fi
CONFIG_FILES=" -Dlogging.path=$LOGS_DIR $LOGGING_CONFIG -Dspring.config.location=$CONF_DIR/ "
echo -e "Starting the $SERVER_NAME ..."
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS $CONFIG_FILES -jar $DEPLOY_DIR/lib/$JAR_NAME > $STDOUT_FILE 2>&1 & echo "OK!"
PIDS=`ps -f | grep java | grep "$DEPLOY_DIR" | awk '{print $2}'`
echo "PID: $PIDS"
echo "STDOUT: $STDOUT_FILE"
- stop.sh
#!/bin/bash
# 项目名称
APPLICATION="${project.artifactId}"
# 项目启动jar包名称
APPLICATION_JAR="${project.build.finalName}.jar"
# 通过项目名称查找到PI,然后kill -9 pid
PID=$(ps -ef | grep "${APPLICATION_JAR}" | grep -v grep | awk '{ print $2 }')
if [[ -z "$PID" ]]
then
echo ${APPLICATION} is already stopped
else
echo kill ${PID}
kill -9 ${PID}
echo ${APPLICATION} stopped successfully
fi
- start.sh
打包项目
- 项目下执行
mvn clean package命令进行打包,打包后的压缩包路径/project_url/target/test01-1.0-SNAPSHOT-bin.tar.gz; - 打包后的项目文件如下:

- 项目下执行
运行项目
- 解压文件:
tar -zxvf /project_url/target/test01-1.0-SNAPSHOT-bin.tar.gz - 进入bin目录下:
cd /project_url/target/test01-1.0-SNAPSHOT/bin - 运行项目:
sh start.sh,运行日志在/project_url/target/test01-1.0-SNAPSHOT/logs路径下 - 关闭项目:
sh stop.sh
- 解压文件:
Apache Maven Assembly自定义打包插件的使用的更多相关文章
- maven-使用assembly自定义打包
用maven管理项目引用依赖很方便,但是打包的时候如果是web包还好,会直接把依赖的jar包打到lib目录中,如果是jar包的话,依赖默认是不打入进去的 这样如果运行环境中没有依赖的jar包,就麻烦了 ...
- Maven学习总结(27)——Maven自定义打包插件maven-assembly-plugin详解
Assembly插件会生成 "assemblies", 此特性等同于的Maven 1 distribution plug-in..该插件不仅支持创建二进制归档文件,也支持创建源码归 ...
- 05 Maven 生命周期和插件
Maven 生命周期和插件 除了坐标.依赖以及仓库之外, Maven 另外两个核心概念是生命周期和插件.在有关 Maven 的日常使用中,命令行的输入往往就对应了生命周期,如 mvn package ...
- 使用Maven的assembly插件实现自定义打包
一.背景 最近我们项目越来越多了,然后我就在想如何才能把基础服务的打包方式统一起来,并且可以实现按照我们的要求来生成,通过研究,我们通过使用maven的assembly插件完美的实现了该需求,爽爆了有 ...
- Maven的assembly插件实现自定义打包部署(包含依赖jar包)
微服务必备 优点: 1.可以直接导入依赖jar包 2.可以添加插件启动 .sh 文件 3.插件的配置以及微服务的统一打包方式 1.首先我们需要在pom.xml中配置maven的assembly插件 & ...
- 【Maven实战技巧】「插件使用专题」Maven-Assembly插件实现自定义打包
前提概要 最近我们项目越来越多了,然后我就在想如何才能把基础服务的打包方式统一起来,并且可以实现按照我们的要求来生成,通过研究,我们通过使用maven的assembly插件完美的实现了该需求,爽爆了有 ...
- Maven打包插件Assembly(七)
1. 在 dubbo 的 provider 项目(实现类项目dubbo-service-impl)中 pom.xml 配置 assembly插件信息 <!-- 指定项目的打包插件信息 --> ...
- java工程打成jar包 - 使用maven assembly插件打包及手动打包
在java工程打包的过程中遇到过不少问题,现在总结一下.一种是典型的maven工程打包,依赖的jar包全都在pom.xml中指定,这种方式打包很方便:另一种是依赖了本机jar包(不能通过pom.xml ...
- assembly打包插件引发的自定义spring标签找不到声明的错误
异常信息:通配符的匹配很全面, 但无法找到元素 的声明. 报的异常信息是关于我们使用的一个自定义的spring标签,这个异常通常的原因可能是读取不到自定义标签的映射. 到META-INF目录下找一下是 ...
- Maven Assembly插件介绍
转自:http://blueram.iteye.com/blog/1684070 已经写得挺好的,就不用重写了. 你是否想要创建一个包含脚本.配置文件以及所有运行时所依赖的元素(jar)Assembl ...
随机推荐
- 创建第一个WebService项目
前提: 保证联网的情况下创建webservice实例,需下载依赖jar 一.创建WebService服务端 1.创建服务端的工程 2.创建javaee的WebServices服务 3.命名server ...
- python 实现AES加解密
AES 只是个基本算法,实现 AES 有几种模式,主要有 ECB.CBC.CFB 和 OFB CTR,直接上代码,此处为AES加密中的CBC模式,EBC模式与CBC模式相比,不需要iv. impor ...
- Clickhouse表引擎探究-ReplacingMergeTree
作者:耿宏宇 1 表引擎简述 1.1 官方描述 MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中.数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合 ...
- md5-有道翻译
网站 aHR0cHMlM0EvL2ZhbnlpLnlvdWRhby5jb20v 测试发现三个值是变化的 一.第一种方法 initiator一步一步找,在t.translate中找到以下内容 这里可以看 ...
- 来自一位十年.net研发老人的吐血整理:.Net技术栈-网址导航
业余时间为什么整理这个? 内容聚合:不用一个一个搜索,我们很快可以进入常用技术官网 提高效率:多看官方文档可以最快,最准确的掌握相关的技术资讯,不用被一些没理解透或者有偏差的技术分享所带偏. 很多有经 ...
- Java基于内存的消息队列实现
Java基于内存的消息队列实现 有需要源码的同学可以去Gitee上下载: https://gitee.com/hyxl-520/memory_message_queue 先看测试情况 需求背景 需求来 ...
- 解决前端发送post 请求出现403,cancled等问题
问题一:页面初始加载,部分接口首次请求options是200,然后第二次post请求cancled状态 1. 检查console控制台报错,如果是接口问题,就不用操心了 2.如果是其他报错,那么就不用 ...
- jjq(友链:https://tg.hszxoj.com/user/475)
- Unity_UIWidgets - 组件Scaffold
UIWidgets - 组件Scaffold 各位兄弟姐妹,想通过Unity来开发UIWidgets的么,想通过UIWi的gets..来开发手机APP么??想么想么,哈哈哈哈哈哈哈哈. 好了,小黑不唠 ...
- 前端基础知识-react(一)个人学习记录 _
待补充 reactive和ref