springboot自定义分环境打包瘦jar,配置文件外置,脚本启动


前言

前言:在springboot统领着java框架半壁江山的今天,作为一个程序员不会使用springboot简直不好意思说自己会java开发。诚然,springboot很好用,在其基础之上去开发很是方便,使用IDEA作为编辑器的话,基本不用怎么配置就能快速启动项目。但是如果打成jar包去运行的话,却有些难受。因为springboot自身的maven打包方式是把整个项目打成一个jar,包括配置文件以及依赖包都在里面,显得有些臃肿,特别是有时候只是想稍微改动一下配置文件的参数却要重新打包部署,实在令人抓狂。而且随着依赖增加,整个jar包会越来越大,每次都整个传输到服务器的话会很慢。所以我就自己去网上查了一下相关资料,自己捣腾出了一套把配置文件和依赖包都外置,脚本启动jar包的方式。


一、添加打包需要文件

因为整个包里面包括三个文件夹
bin:放启动项目脚本
conf:放配置文件
lib:放启动项目jar及相关依赖jar
所以得在项目里新建一些文件夹
在创建好的springboot项目的main文件夹下创建如下文件夹

  • main(<—这是项目的main文件夹)
    • assembly
    • config
    • starup

贴一下自己的项目结构
在这里插入图片描述
assembly.xml文件内容:

<assembly>
	<!--用于给生成的包名添加后缀,可自行命名-->
	<id>assembly</id>
	<formats>
		<!--生成压缩包的后缀,可以生成zip-->
		<!--这个压缩包在linux下的解压命令是 tar -zxvf -->
		<format>tar.gz</format>
	</formats>
	<!--tar.gz压缩包下是否生成和项目名相同的根目录-->
	<includeBaseDirectory>true</includeBaseDirectory>
	<fileSets>
		<fileSet>
			<!--把startup里面的启动项目脚本添加到压缩包的bin文件夹下面-->
			<!--注意!!! startup文件夹里面的启动脚本编码必须是LF的,
			CR或者CRLF在linux下使用会报错-->
			<directory>src/main/startup</directory>
			<outputDirectory>bin</outputDirectory>
			<!-- 文件权限 读权限为4;写权限为2;执行权限为1;第一位7表示文件所有者所拥有的权限;
			 第二位5表示文件所有者同组用户所拥有的权限;
			 第三位5表示公共用户所拥有的权限-->
			<fileMode>0755</fileMode>
		</fileSet>
		<fileSet>
			<!--把config里项目启动需要的配置文件添加到压缩包的conf文件夹下面-->
			<!--${profile.active}占位符在pom.xml文件处理-->
			<directory>src/main/config/${profile.active}</directory>
			<outputDirectory>conf</outputDirectory>
			<fileMode>0644</fileMode>
		</fileSet>
	</fileSets>
	<dependencySets>
		<dependencySet>
			<!--是否把本项目添加到依赖文件夹下,true则把项目启动的jar包放到压缩包的lib文件夹下面-->
			<useProjectArtifact>true</useProjectArtifact>
			<outputDirectory>lib</outputDirectory>
			<!-- 默认即为runtime -->
			<scope>runtime</scope>
		</dependencySet>
	</dependencySets>
</assembly>

startup文件夹下的四个shell脚本

start.sh
整个内容只需要修改SERVER_NAMEAPPLICATION_JAR,其他不用动

#!/bin/bash
cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf

#SERVER_NAME和APPLICATION_JAR根据自身项目填写
SERVER_NAME='服务名,自行填写'
APPLICATION_JAR=项目启动jar的名字及后缀,例子:xxx-0.0.1-SNAPSHOT.jar

if [ -z "$SERVER_NAME" ]; then
    SERVER_NAME=`hostname`
fi

PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'`
if [ -n "$PIDS" ]; then
    echo "ERROR: The $SERVER_NAME already started!"
    echo "PID: $PIDS"
    exit 1
fi

LOGS_DIR=$DEPLOY_DIR/logs

if [ ! -d $LOGS_DIR ]; then
    mkdir $LOGS_DIR
fi

#STDOUT_FILE=$LOGS_DIR/stdout.log
STDOUT_FILE=/dev/null

LIB_DIR=$DEPLOY_DIR/lib
LIB_JARS=`ls $LIB_DIR|grep .jar|awk '{print "'$LIB_DIR'/"$0}'|tr "\n" ":"`

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 -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
else
    JAVA_MEM_OPTS=" -server -Xms1g -Xmx1g -XX:PermSize=128m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi

CONFIG=""
for file_a in ${CONF_DIR}/*
do
    CONFIG=$CONFIG$file_a","
done
CONFIG=${CONFIG%?}
echo "using config => $CONFIG"
echo -e "Starting the $SERVER_NAME ...\c"
JAR=${LIB_DIR}/${APPLICATION_JAR}
nohup java -jar $JAR $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS  --spring.config.additional-location=$CONFIG > $STDOUT_FILE 2>&1 &

echo "OK!"
PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'`
echo "PID: $PIDS"
echo "STDOUT: $STDOUT_FILE"

stop.sh

#!/bin/bash
cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf

SERVER_NAME='服务名,自行填写'

PIDS=`ps -ef | grep java | grep "$CONF_DIR" |awk '{print $2}'`
if [ -z "$PIDS" ]; then
    echo "ERROR: The $SERVER_NAME does not started!"
    exit 1
fi

echo -e "Stopping the $SERVER_NAME ...\c"
for PID in $PIDS ; do
    kill $PID > /dev/null 2>&1
done

COUNT=0
while [ $COUNT -lt 1 ]; do    
    echo -e ".\c"
    sleep 1
    COUNT=1
    for PID in $PIDS ; do
        PID_EXIST=`ps -f -p $PID | grep java`
        if [ -n "$PID_EXIST" ]; then
            COUNT=0
            break
        fi
    done
done

echo "OK!"
echo "PID: $PIDS"

restart.sh

#!/bin/bash
cd `dirname $0`
./stop.sh
./start.sh

server.sh

#!/bin/bash
cd `dirname $0`
if [ "$1" = "start" ]; then
	./start.sh
else
	if [ "$1" = "stop" ]; then
		./stop.sh
	else
		if [ "$1" = "debug" ]; then
			./start.sh debug
		else
			if [ "$1" = "restart" ]; then
				./restart.sh
			else
				if [ "$1" = "dump" ]; then
					./dump.sh
				else
					echo "ERROR: Please input argument: start or stop or debug or restart or dump"
				    exit 1
				fi
			fi
		fi
	fi
fi

至于config里面 test pro dev这几个文件夹,放的就是springboot的yml配置文件,然后做了分环境处理,在打包的时候外置配置文件。而配置文件怎么分环境打包,在pom.xml文件里面处理。

二、修改pom.xml文件

先贴个正常springboot项目创建后pom.xml的基本内容,用作对比

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

下面是pom.xml配置,重点!!!

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        

    </dependencies>
	<!--下面为变更的内容-->
	<!--多环境maven打包配置-->
    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <!--profile.active是自己定义的节点,
                可以根据这个节点的值在pom.xml的其他地方或者相关文件使用占位符-->
                <!--这里就是处理assembly.xml里的${profile.active}占位符的-->
                <profile.active>dev</profile.active>
            </properties>
            <activation>
                <!--默认激活dev环境打包-->
                <activeByDefault>true</activeByDefault>
                <!--这个标签其实跟<profile.active>差不多,都是用来做占位符的值-->
                <property>
                    <name>env</name>
                    <value>dev</value>
                </property>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <profile.active>test</profile.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
                <property>
                    <name>env</name>
                    <value>test</value>
                </property>
            </activation>
        </profile>
        <profile>
            <id>pro</id>
            <properties>
                <profile.active>pro</profile.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
                <property>
                    <name>env</name>
                    <value>pro</value>
                </property>
            </activation>
        </profile>
    </profiles>
	
	
    <build>
    	<resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
      
        <plugins>
        	<!--springboot原有的打包插件,不能注释掉,
        	不然maven打包后生成的jar包启动会报ClassNotFoundException异常-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
				
				<!--去除springboot jar包里的lib文件夹-->
				<!--这里特别说明一下,正常生成的项目启动jar里面的BOOT-INF文件夹
				下除了有放置我们自己的字节码的classes文件夹,还会有个lib文件夹,
				它里面放的是依赖的jar包。而下面这两个节点就是为了去除lib文件夹,因为依赖jar都外置了,
				就没必要把依赖jar再放进项目启动jar里面了。去掉依赖jar的项目启动jar也叫瘦jar-->
                <configuration>
                    <includes>
                        <include>
                        	<!--设置为nothing表示项目打成的jar包不包含外部依赖jar包-->
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                
            </plugin>
			
			<!--添加配置跳过测试-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <archive>
                        <manifest>
                            <!--运行jar包时运行的主类,要求类全名-->
                          	<mainClass>com.xxx.xxx.XxxApplication</mainClass>
                            <!-- 是否指定项目classpath下的依赖 -->
                            <!--这个配置就是开启项目启动jar寻找依赖jar-->
                            <addClasspath>true</addClasspath>
                            <!-- 指定依赖的时候声明前缀 -->
                            <!--项目启动jar寻找依赖jar的路径,因为项目启动jar和依赖jar
                            同在压缩包的lib文件夹下,所以用./-->
                            <classpathPrefix>./</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>./</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <!-- 配置执行器 -->
                    <execution>
                    	<!--名字任意 -->
                        <id>make-assembly</id>
                        <!-- 绑定到package生命周期阶段上 -->
                        <phase>package</phase>
                        <goals>
                            <!-- 只运行一次 -->
                            <goal>single</goal>
                        </goals>
                        <configuration>
                        	<!--项目名称-->
                            <finalName>${project.name}</finalName>
                            <!--assembly配置描述文件路径-->
                            <descriptors>
                                <descriptor>src/main/assembly/assembly.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
	
	
</project>

当上面所有东西都配置好,在pom.xml文件所在的文件夹下执行命令
mvn clean package -Dmaven.test.skip=true -Ptest (PS:其中-P后面可选dev/test/pro,这也就是分环境打包了)就可以在target文件夹下生成对应的tar.gz压缩包:项目名-assembly.tar
压缩包里的结构如下

  • xxx(以项目名命名的文件夹)
    • bin (放启动shell脚本)
    • conf (放配置文件)
    • lib (放项目启动jar及依赖jar)

只要把 tar.gz压缩包放到服务器解压,再执行 start.sh就能启动项目了

总结

以上就是全文内容了,欢迎留言交流。

转载请声明出处!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值