利用spring-boot-thin-launcher插件分离jar包的依赖和配置

导读:本篇文章讲解 利用spring-boot-thin-launcher插件分离jar包的依赖和配置,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Spring Boot项目可以通过spring-boot-maven-plugin插件打包生成一个可执行的jar包,这样可以脱离web容器(例如tomcat)直接运行。但默认情况下spring-boot-maven-plugin打出来的包是一个fat jar,即将所有的依赖全部打进了jar包当中,这样的jar包体积很大,每次更新系统的时候都需要完整替换整个jar包(本地还好,如果是云服务器,网速慢了每次上传文件都想砸电脑π__π)。此外,系统切换环境时,也同时需要切换配置参数,虽然可以使用配置中心或者利用命令行参数修改配置,但有时候也免不了直接需要修改配置文件,这样的话就有必要将配置文件从jar包中分离出来,单独存放。

Spring社区大概也考虑到了部分开发者有这样的需求,所以提供了spring-boot-thin-launcher这个插件用来将项目的依赖和配置从jar包中分离出去。这个插件虽然是放到spring-projects-experimental(意思就是实验性质的项目)当中的,但从我使用的经验来看应该是比较稳定的,能够满足绝大部分场景的需求。废话少说,还是先上代码吧:

<build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <!--项目的执行入口-->
                    <mainClass>com.example.Application</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.boot.experimental</groupId>
                        <artifactId>spring-boot-thin-layout</artifactId>
                        <version>1.0.12.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot.experimental</groupId>
                <artifactId>spring-boot-thin-maven-plugin</artifactId>
                <version>1.0.12.RELEASE</version>
                <executions>
                    <execution>
                        <!--在编译时下载依赖包 -->
                        <id>resolve</id>
                        <goals>
                            <goal>resolve</goal>
                        </goals>
                        <inherited>false</inherited>
                    </execution>
                </executions>
            </plugin>
            <!--移动配置文件到外部文件夹-->
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                                <move file="${project.build.directory}/classes/application.yml" todir="${project.build.directory}/thin/root/config"/>
                                <copy todir="${project.build.directory}/thin/root/">
                                    <fileset dir="${basedir}/bin"/>
                                </copy>
                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

在maven-antrun-plugin中可以根据需要定义一些额外的任务,比如移动其它的配置文件,或者将外部的一些文件加入到项目目录中(比如执行脚本等)。
这样配置后,打包以后的target目录大概是这样的:
target目录结构.png
其中thin目录下面就可以作为整个项目的部署目录了,config是配置文件的存放目录,respository下面是所有的依赖包,backend-2.0.jar中仅包含了项目自身的资源,体积比之前小太多了。
##运行原理
那为什么执行时,系统知道自动去外部加载依赖和配置呢?这个问题需要首先了解打包后的结构,把backend-2.0.jar解压之后,会发现除了我们自己的类和资源以外,还多了一个类:
org.springframework.boot.loader.wrapper.ThinJarWrapper,其实我们在运行项目时,这个类才是真正的项目入口,它会在默认位置查找项目相关的依赖,如果没有找到,甚至还会从指定的maven仓库中直接下载,所以启动时系统能够识别到外部的依赖包。至于外部配置,是因为Spring Boot框架在读取配置文件时,会默认读取几个目录下的配置文件,其中优先级最高的就是当前目录下的config目录(所以config目录的名字不能改成其它的)。

执行jar包的时候需要注意,要额外添加一个参数来指定依赖包所在的仓库位置(在我们的配置中就在jar包的当前文件夹),例如:-Dthin.root=. 默认的位置是${user.home}/.m2,如果仓库中没有需要的依赖,启动jar包时还会自动连接远程仓库进行下载,导致启动时间非常长,这一点需要注意。spring-boot-thin-launcher还有很多可配置的参数,具体可以到 官网 上自行查看。

另外附上一个通用的spring-boot-thin-launcher打包文件的启动脚本:

#!/bin/bash
#这里指定需要运行的jar包的名字
APP_NAME="your-jar-name.jar"
JVM_ARGS="-Xms512M -Xmx2048M -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/log/heap.hprof"
THIN_ARGS="-Dthin.root=. -Dthin.offline=true"
#使用说明,用来提示输入参数
usage() {
    echo "Usage: sh 执行脚本.sh [start|stop|restart|status|run]"
    exit 1
}
 
#检查程序是否在运行
is_exist(){
  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
  #如果不存在返回1,存在返回0
  if [ -z "${pid}" ]; then
   return 1
  else
    return 0
  fi
}
 
#后台启动
start(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is already running. pid=${pid} ."
  else
    echo "${APP_NAME} running with args: nohup java $THIN_ARGS -jar $JVM_ARGS $APP_NAME "
    nohup java $THIN_ARGS -jar $JVM_ARGS $APP_NAME >> catalina.out 2>&1 &
  fi
}
#前台启动
run(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is already running. pid=${pid} ."
  else
    echo "${APP_NAME} running with args: java $THIN_ARGS -jar $JVM_ARGS $APP_NAME"
    java $THIN_ARGS -jar $JVM_ARGS $APP_NAME 
  fi
}
 
#停止方法
stop(){
  is_exist
  if [ $? -eq "0" ]; then
    kill -9 $pid
  else
    echo "${APP_NAME} is not running"
  fi
}
 
#输出运行状态
status(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is running. Pid is ${pid}"
  else
    echo "${APP_NAME} is NOT running."
  fi
}
 
#重启
restart(){
  stop
  start
}
 
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
  "start")
    start
    ;;
  "run")
    run
    ;;
  "stop")
    stop
    ;;
  "status")
    status
    ;;
  "restart")
    restart
    ;;
  *)
    usage
    ;;
esac

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15715.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!