前言
- 本文主要记录在SpringBoot项目中使用Apache Maven Assembly插件进行打包的相关内容;
- 官网说明:https://maven.apache.org/plugins/maven-assembly-plugin/
概述
- 是什么:Apache Maven Assembly是Maven的程序集插件使开发人员能够将项目输出合并到单个可分发的存档中,该存档还包含依赖项、模块、站点文档和其他文件。
- 作用:可以实现自定义打包,从而实现打包项目可以外挂yml配置文件,提供shell运维脚本,大大降低运维成本,比较适用于小规模的SpringBoot项目(大规模的项目推荐docker容器部署)
配置说明
-
引入插件(pom文件中)
<project> ... <build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> <version>2.3.7.RELEASEversion> <configuration> <mainClass>com.alan.SpringBootMainmainClass> configuration> <executions> <execution> <goals> <goal>repackagegoal> goals> execution> executions> plugin> <plugin> <groupId>org.apache.maven.pluginsgroupId> <artifactId>maven-assembly-pluginartifactId> <version>3.5.0version> <configuration> <descriptors> <descriptor>src/main/assembly/assembly.xmldescriptor> descriptors> configuration> <executions> <execution> <id>make-assemblyid> <phase>packagephase> <goals> <goal>singlegoal> goals> execution> executions> plugin> plugins> build> project> -
配置assembly文件(在pom中设定的位置下创建,我这里是src/main/assembly/assembly.xml)
<assembly> <id>binid> <formats> <format>tar.gzformat> formats> <includeBaseDirectory>trueincludeBaseDirectory> <dependencySets> <dependencySet> <useProjectArtifact>trueuseProjectArtifact> <outputDirectory>liboutputDirectory> dependencySet> dependencySets> <fileSets> <fileSet> <directory>src/main/assembly/bindirectory> <outputDirectory>binoutputDirectory> <fileMode>0755fileMode> <lineEnding>unixlineEnding> <filtered>truefiltered> fileSet> <fileSet> <directory>src/main/assembly/configdirectory> <outputDirectory>configoutputDirectory> <fileMode>0644fileMode> fileSet> <fileSet> <directory>src/main/resourcesdirectory> <outputDirectory>/configoutputDirectory> <includes> <include>**/*.xmlinclude> <include>**/*.propertiesinclude> <include>**/*.ymlinclude> includes> <filtered>truefiltered> fileSet> <fileSet> <directory>targetdirectory> <outputDirectory>liboutputDirectory> <includes> <include>*.jarinclude> includes> fileSet> <fileSet> <directory>.directory> <outputDirectory>docsoutputDirectory> <includes> <include>*.mdinclude> includes> <fileMode>0644fileMode> fileSet> <fileSet> <directory>docsdirectory> <outputDirectory>docsoutputDirectory> <fileMode>0644fileMode> fileSet> <fileSet> <directory>src/main/assembly/docsdirectory> <outputDirectory>docsoutputDirectory> <fileMode>0644fileMode> 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
- 解压文件: