Backend Development 15 min read

Spring Boot Packaging with Maven Profiles and a Shell Deployment Tool

This article explains how to use Maven profiles to manage multiple Spring Boot environments, configure the maven‑assembly‑plugin to create a zip release containing the jar, configuration files and a custom shell script, and then deploy and control the application on Linux using the provided shenniu_publish.sh tool.

IT Xianyu
IT Xianyu
IT Xianyu
Spring Boot Packaging with Maven Profiles and a Shell Deployment Tool

The guide shows how to package a Spring Boot application for different deployment environments (dev, test, uat, prod) by defining Maven <profiles> with environment‑specific properties such as activeProfile , package-name and boot-main . Two methods for selecting a profile are described, and the second method (Maven profiles) is demonstrated.

In the Maven pom.xml a <profiles> section is added:

<profiles>
  <profile>
    <id>node</id>
    <properties>
      <!-- parameters passed to the script -->
      <activeProfile>node</activeProfile>
      <package-name>${scripts_packageName}</package-name>
      <boot-main>${scripts_bootMain}</boot-main>
    </properties>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
  </profile>
  ... (additional profiles node1, node2) ...
</profiles>

The maven‑assembly‑plugin and maven‑jar‑plugin are configured to produce a zip file that contains the compiled jar, a conf directory with configuration files, a lib directory with dependencies, and the deployment script:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.6</version>
  <configuration>
    <archive>
      <addMavenDescriptor>false</addMavenDescriptor>
      <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>lib/</classpathPrefix>
        <mainClass>${scripts_bootMain}</mainClass>
      </manifest>
    </archive>
    <excludes>
      <exclude>**/*.yml</exclude>
      <exclude>**/*.properties</exclude>
      <exclude>**/*.xml</exclude>
      <exclude>**/*.sh</exclude>
    </excludes>
  </configuration>
  <executions>
    <execution>
      <id>make-a-jar</id>
      <phase>compile</phase>
      <goals>
        <goal>jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.4</version>
  <configuration>
    <descriptors>
      <descriptor>${project.basedir}/src/main/assembly/assembly.xml</descriptor>
    </descriptors>
  </configuration>
  <executions>
    <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The accompanying assembly.xml defines the zip format, includes the conf folder, the lib folder, the compiled jar and the script, and sets file permissions (777) for the script:

<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>${activeProfile}</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>${package-name}-${activeProfile}/lib</outputDirectory>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <directory>${project.basedir}/src/main/profiles/${activeProfile}</directory>
      <outputDirectory>${package-name}-${activeProfile}/conf</outputDirectory>
      <includes>
        <include>**/*</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${project.basedir}/src/main/scripts</directory>
      <outputDirectory></outputDirectory>
      <includes>
        <include>**/*</include>
      </includes>
      <fileMode>777</fileMode>
      <directoryMode>777</directoryMode>
      <filtered>true</filtered>
    </fileSet>
    <fileSet>
      <directory>${project.build.directory}</directory>
      <outputDirectory>${package-name}-${activeProfile}/</outputDirectory>
      <includes>
        <include>*.jar</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>

The resulting zip can be uploaded to a Linux server, unpacked, and managed with the provided shenniu_publish.sh script. The script supports the following commands: unzip (extract and start), start , stop , and restart . It also detects the running PID, chooses the launch mode ( java -cp or java -jar ), and tails the output log.

#!/usr/bin/env bash
# 可变参数变量
languageType="javac"   # 支持 java,javac,netcore 发布
# 参数值由 pom 文件传递
baseZipName="${package-name}-${activeProfile}"
packageName="${package-name}"
mainclass="${boot-main}"

basePath=$(cd `dirname $0`/; pwd)
baseZipPath="${basePath}/${baseZipName}.zip"
baseDirPath="${basePath}"
pid=

function shenniu_unzip() {
  echo "解压---------------------------------------------"
  if [ ! `find ${baseZipPath}` ]; then
    echo "不存在压缩包:${baseZipPath}"
  else
    echo "解压磁盘路径:${baseDirPath}/${baseZipName}"
    echo "开始解压..."
    unzip -od ${baseDirPath}/${baseZipName} ${baseZipPath}
    chmod +x ${baseDirPath}/${baseZipName}/${packageName}
    echo "解压完成。"
  fi
}

function getPid() {
  echo "检测状态---------------------------------------------"
  pid=`ps -ef | grep -n ${packageName} | grep -v grep | awk '{print $2}'`
  if [ ${pid} ]; then
    echo "运行pid:${pid}"
  else
    echo "未运行"
  fi
}

function start() {
  stop
  if [ ${pid} ]; then
    echo "停止程序失败,无法启动"
  else
    echo "启动程序---------------------------------------------"
    read -p "输入程序类型(java,javac,netcore),下一步按回车键(默认:${languageType}):" read_languageType
    if [ ${read_languageType} ]; then
      languageType=${read_languageType}
    fi
    echo "选择程序类型:${languageType}"
    cd ${baseDirPath}/${baseZipName}
    if [ "${languageType}" == "javac" ]; then
      if [ ${mainclass} ]; then
        nohup java -cp conf:lib\*.jar:${packageName}.jar ${mainclass} >${baseDirPath}/${packageName}.out 2>&1 &
      fi
    elif [ "${languageType}" == "java" ]; then
      nohup java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar > /dev/null 2>&1 &
    elif [ "${languageType}" == "netcore" ]; then
      nohup ${baseDirPath}/${baseZipName}/${packageName} > /dev/null 2>&1 &
    fi
    getPid
    if [ ${pid} ]; then
      echo "已启动"
      tail -n 50 -f ${baseDirPath}/${packageName}.out
    else
      echo "启动失败"
    fi
  fi
}

function stop() {
  getPid
  if [ ${pid} ]; then
    echo "停止程序---------------------------------------------"
    kill -9 ${pid}
    getPid
    if [ ${pid} ]; then
      echo "停止失败"
    else
      echo "停止成功"
    fi
  fi
}

if [ ${#} -ge 1 ]; then
  case ${1} in
    "start") start ;;
    "restart") start ;;
    "stop") stop ;;
    "unzip") shenniu_unzip ; start ;;
    *) echo "${1}无任何操作" ;;
  esac
else
  echo "命令如下命令:
    unzip:解压并启动
    start:启动
    stop:停止进程
    restart:重启
    示例命令如:./shenniu_publish.sh start"
fi

Before the first execution on Linux, convert the script to Unix line endings with vim (set ff=unix) to avoid format errors. After extraction, run ./shenniu_publish.sh start to launch the Spring Boot service; stop and restart work similarly. The full project, including the script, is available at GitHub .

deploymentmavenLinuxSpring Bootshell scriptProfilesAssembly Plugin
IT Xianyu
Written by

IT Xianyu

We share common IT technologies (Java, Web, SQL, etc.) and practical applications of emerging software development techniques. New articles are posted daily. Follow IT Xianyu to stay ahead in tech. The IT Xianyu series is being regularly updated.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.