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

 更新时间:2023年09月01日 10:09:39   作者:david'fantasy  
这篇文章主要介绍了spring-boot-thin-launcher插件分离jar包的依赖和配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

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

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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MybatisPlus代码生成器含XML文件详解

    MybatisPlus代码生成器含XML文件详解

    这篇文章主要介绍了MybatisPlus代码生成器含XML文件详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 详解Mybatis中javaType和ofType的区别

    详解Mybatis中javaType和ofType的区别

    本文主要介绍了详解Mybatis中javaType和ofType的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Eclipse添加xml文件提示及Hibernate配置学习

    Eclipse添加xml文件提示及Hibernate配置学习

    文件提示功能在开发过程中很实用的,本文实现了一个Eclipse添加xml文件提示,感兴趣的朋友可以了解下啊,希望本文对你有所帮助
    2013-01-01
  • 关于JavaEE匿名内部类和Lambda表达式的注意事项

    关于JavaEE匿名内部类和Lambda表达式的注意事项

    这篇文章主要介绍了关于JavaEE匿名内部类和Lambda表达式的注意事项,匿名内部类顾名思义是没有修饰符甚至没有名称的内部类,使用匿名内部类需要注意哪些地方,我们一起来看看吧
    2023-03-03
  • springboot如何读取配置文件(application.yml)中的属性值

    springboot如何读取配置文件(application.yml)中的属性值

    本篇文章主要介绍了springboot如何读取配置文件(application.yml)中的属性值,具有一定的参考价值,有兴趣的小伙伴可以了解一下
    2017-04-04
  • springMVC框架下JQuery传递并解析Json数据

    springMVC框架下JQuery传递并解析Json数据

    json作为一种轻量级的数据交换格式,在前后台数据交换中占据着非常重要的地位,这篇文章主要介绍了springMVC框架下JQuery传递并解析Json数据,有兴趣的可以了解一下。
    2017-01-01
  • 关于BufferedReader的read()和readLine()的区别

    关于BufferedReader的read()和readLine()的区别

    这篇文章主要介绍了关于BufferedReader的read()和readLine()的区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 关于如何正确地定义Java内部类方法详解

    关于如何正确地定义Java内部类方法详解

    在Java中,我们通常是把不同的类创建在不同的包里面,对于同一个包里的类来说,它们都是同一层次的,但其实还有另一种情况,有些类可以被定义在另一个类的内部,本文将详细带你了解如何正确地定义Java内部类,需要的朋友可以参考下
    2023-05-05
  • Spring注解解析之@ImportResource

    Spring注解解析之@ImportResource

    之前我们使用spring,最多的还是通过xml配置文件的方式来配置spring bean等内容,随着注解的广泛应用和spring4中Java config的引入,xml配置文件方式逐步被替换,但是如果是想要使用xml配置文件方式的话,也可以通过@ImportResource注解来实现,下面我们来一起看下如何使用.
    2021-05-05
  • Spring如何使用注解的方式创建bean

    Spring如何使用注解的方式创建bean

    这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11

最新评论