85 总结一下最近遇到的一些 jar发布 相关的知识

news2024/9/29 15:34:37

前言

呵呵 最近有一些构建服务, 发布服务的一些需求 

我们这里的服务 一般来说是 java application, spring boot application 

针对发布, 当然最好是 增量发布, 尽量的减少需要传递给 发布服务器 的资源的大小  

比如 我的这个 java application, 可能会存在很多依赖, 常规有很多种做法 

1. 吧 application 和其依赖绑定打成一个 fat jar, 然后传到发布服务器上面, java -jar $jar 

2. 通过 classpath 来关联依赖的 jar, java -classpath $classpath -jar $appJar 或者 java -classpath $classpath:$appJar $mainClazz 

假设依赖很多的话, 方式 显然会传递很多 大概率不会变化的依赖的数据, 造成一些 不必要的麻烦, 时间开销 等等 

我们这里会 介绍一些场景来尽可能的减少发布所需要的一些数据, 将一些稳定的数据 一直保存在发布服务器上面就好 

 

但是依然会存在一些问题, 希望您看完之后 有所收获 

1. 如何更加 轻量级 的发布 java application 

1. 比如 $classpath 太长的情况下, 怎么处理, 命令行支持的命令的长度是有限的, 应该怎么处理 ? 

2. spring boot 的包包括了依赖, 应该怎么 更加轻量级的发布 ? 

 

 

java application 启动的一些方式

抽象的来说又如下几种启动方式 

1. java -classpath $classpath $mainClazz

2. java -classpath $classpath -jar $jar 

 

但是我们这里要讨论如下几种情况, 当然 都可以抽象为上面两种方式, 但是 在一些特殊的场景有一些特殊的使用, 因此我们单独拎出来 

1. java -classpath $classpath $mainClazz
2. java -jar $jar
3. java  -classpath $classpath -jar $jar
4. java CommandlineRunner $classpathFile $mainClazz
5. java -jar $shortenJar $mainClazz
6. java -jar $springbootJar

 

1. java -classpath $classpath $mainClazz

这个就是我们最常见的了, 通过 -classpath 选项指定 classpath, 然后 $mainClazz 是启动类, 寻找 classpath 中的 $mainClazz, 然后调用 $mainClazz 的 main 方法 

不多赘述 

 

2. java -jar $jar

这个就是 直接通过 jar 来启动, 清单文件中包含了需要的 $classpath 和 $mainClazz 

寻找 classpath 中的 $mainClazz, 然后调用 $mainClazz 的 main 方法 

不多赘述 

 

3. java -classpath $classpath -jar $jar

在 2 的基础上增加了 指定 -classpath 

不多赘述 

 

4. java CommandlineRunner $classpathFile $mainClazz

这个就是 idea 提供的缩短 classpath 的方案之一 

通过 CommandlineRunner 代理一次, 从外部读取 classpath, 放入 classloader, 然后再 查找 $mainClazz, 调用 main 方法 

具体的实现, 请参见  idea 的 CommandlineRunner 

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEwMzkzMzI=,size_16,color_FFFFFF,t_70

 

然后启动的方式大致如下, 抽象的来说可以归类为 java -classpath $classpath $mainClazz 

/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 com.intellij.rt.execution.CommandLineWrapper /private/var/folders/pw/lb8dvl7d6474r5plrnwtcp180000gn/T/idea_classpath880125671 com.hx.test12.Test02WechatJson

然后 $claspathFile 中的内容大致如下 

/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/lib/jconsole.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/lib/packager.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/lib/sa-jdi.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/lib/tools.jar
/Users/jerry/IdeaProjects/HelloWorld/target/classes
/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar
/Users/jerry/.m2/repository/com/hx/HXLog/0.0.2/HXLog-0.0.2.jar
/Users/jerry/.m2/repository/com/hx/HXCommon/0.0.2/HXCommon-0.0.2.jar
/Users/jerry/.m2/repository/com/hx/HXJson/0.0.2/HXJson-0.0.2.jar

 

5. java -jar $shortenJar $mainClazz 

这个就是 idea 提供的缩短 classpath 的方案之一 

idea 生成一个 $classpathJar 里面通过 清单文件 指定了所有的 classpath, 然后搜索 $mainClazz, 调用 main 方法 

 

然后启动的方式大致如下, 抽象的来说可以归类为 java -classpath $classpath $mainClazz 

/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /private/var/folders/pw/lb8dvl7d6474r5plrnwtcp180000gn/T/classpath298101813.jar com.hx.test12.Test02WechatJson

$shortenJar 里面仅仅包含一个 清单文件, 里面的 classpath 如下

注意清单文件是有规范的, 比如这里一行多少字符, 换行之后几个空格, 这些都是有约束的 

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEwMzkzMzI=,size_16,color_FFFFFF,t_70

 

6. java -jar $springbootJar

我们做 spring boot 项目, 打包的话 可以直接生成一个可执行的 jar

直接 java -jar $springbootJar 就可以启动服务了, 非常方便 

当然 也是 spring 代理了一次, 后面将执行工作交给了我们的 XXXApplication 

里面的查询 类 spring 自己封装了一套 seach 体系 

 

 

如何更加 轻量级 的发布 java application 

呵呵 这里主要介绍一些 我们平时项目中应该怎么更加轻量级的发布 普通的 java application 

首先 打包只需要打包 我们经常变化的部分 

其他的相对比较固定的依赖 等等, 可以直接上传到服务器 我们通过 classpath 来关联 

 

$classpath 太长的情况我们应该怎么处理?, idea 提供了两种解决方式 

但是 我们这里显然是更加适合 CommandlineRunner 的处理方式, 因此 需要自己吧 CommandlineRunner dump 出来, 可能需要稍微做一些调整, 原有的 CommandlineRunner 在读取了 $classpathFile 之后就删除了该文件, 我们这里 显然是不想删除 $classpathFile 

思路 大体就这些, 接下来 分享一些 发布相关脚本  

 

总体分为三类文件, 一类是 common 脚本, 一类是应用脚本, 一类是 CommandlineRunner 所在的包 

common 这边主要是提供一些公共的服务, 比如 启动, 关闭, 备份 等等 

应用这边主要提供 启动服务, 关闭服务, 备份服务, 重启服务, 发布服务 等等 

CommandlineRunner 主要是提供 shorten $classpath 的服务 

CommandlineRunner 我们这里就不多赘述了, 自己参见 idea 的 CommandlineRunner 即可, 我这里也只是封装了一个 bootstrap/CommandlineRunner.jar 而已 

 

common/backup.sh 


echo " backup start ... "

SCRIPT_DIR=$(cd $(dirname $0); pwd)
MY_BASE_DEFAULT=$(cd $SCRIPT_DIR; cd ..; pwd)
PWD=`pwd`
MY_BASE=${MY_BASE-$MY_BASE_DEFAULT}
project=$1
mainClazz=$2

echo -e " \
env as follows \n \
SCRIPT_DIR : $SCRIPT_DIR \n pwd : $PWD \n MY_BASE : $MY_BASE \n project : $project \n \
mainClazz : $mainClazz \
"

if [ "$project" = "" ]; then
    echo " please specify project at \$1 "
    exit
fi
if [ "$mainClazz" = "" ]; then
    echo " please specify main clazz file at \$2 "
    exit
fi

projectFolder=$MY_BASE/$project
if [ ! -d "$projectFolder" ]; then
    echo " project folder $projectFolder does not exists, please check that "
    exit
fi

# do business
curDate=$(date "+%Y-%m-%d")
curTime=$(date "+%H-%M-%S")

bakDir="$MY_BASE/bak/$curDate/$project/$curTime"
mkdir -p "$bakDir"

echo " backup project $project to $bakDir "

# 1. zip dev/bak first, then transfer bak.zip 
zip -r $projectFolder/dev/bak.zip $projectFolder/dev/bak/* 
rm -rf $projectFolder/dev/bak/*
mv $projectFolder/dev/bak.zip $projectFolder/dev/bak/bak.zip
cp -r $projectFolder/dev/bak/* $bakDir/ 2>/dev/null
echo " copied /dev/bak/* in project $project to $bakDir "

echo " backup end ... "

 

common/commandLineWrapperStartUp.sh


echo " startup start ... "

SCRIPT_DIR=$(cd $(dirname $0); pwd)
MY_BASE_DEFAULT=$(cd $SCRIPT_DIR; cd ..; pwd)
PWD=`pwd`
MY_BASE=${MY_BASE-$MY_BASE_DEFAULT}
project=$1
ideaClasspathFile=$2
mainClazz=$3
mainArgs=$4

echo -e " \
env as follows \n \
SCRIPT_DIR : $SCRIPT_DIR \n pwd : $PWD \n MY_BASE : $MY_BASE \n project : $project \n \
ideaClasspathFile : $ideaClasspathFile \n mainClazz : $mainClazz \n mainArgs : $mainArgs \
"

if [ "$project" = "" ]; then
    echo " please specify project at \$1 "
    exit
fi
if [ "$ideaClasspathFile" = "" ]; then
    echo " please specify idea classpath file at \$2 "
    exit 
fi
if [ "$mainClazz" = "" ]; then
    echo " please specify main clazz file at \$3 "
    exit
fi

projectFolder=$MY_BASE/$project
ideaClasspathFileFullpath=$MY_BASE/$project/$ideaClasspathFile
if [ ! -d "$projectFolder" ]; then
    echo " project folder $projectFolder does not exists, please check that "
    exit
fi
if [ ! -f "$ideaClasspathFileFullpath" ]; then
    echo " idea classpath file $ideaClasspathFileFullpath does not exists, please check that "
    exit
fi


EXISTS_PID=`jps -lvm | grep $mainClazz | grep -v grep | awk '{print $1}'`
if [ "$EXISTS_PID" = "" ]; then
#    nohup java -cp $MY_BASE/common/Bootstrap.jar com.hx.idea.CommandLineWrapper $ideaClasspathFile $mainClazz $mainArgs > ./logs/nohup.log 2>&1 &
    java -jar /meiya/bootstrap/CommandLineWrapper.jar $ideaClasspathFileFullpath $mainClazz $mainArgs > logs/nohup.log  2>&1 &
	
	# tail log
    sleep 3s
    EXISTS_PID=`jps -lvm | grep $mainClazz | grep -v grep | awk '{print $1}'`
    echo " the main class $mainClazz startup succeed, running at $EXISTS_PID "
	tail -f logs/nohup.log
else
    echo " the main class $mainClazz already running at $EXISTS_PID "
fi

echo " startup end ... "

 

common/commandLineWrapperShutdown.sh


echo " shutdown start ... "

SCRIPT_DIR=$(cd $(dirname $0); pwd)
MY_BASE_DEFAULT=$(cd $SCRIPT_DIR; cd ..; pwd)
PWD=`pwd`
MY_BASE=${MY_BASE-$MY_BASE_DEFAULT}
project=$1
mainClazz=$2

echo -e " \
env as follows \n \
SCRIPT_DIR : $SCRIPT_DIR \n pwd : $PWD \n MY_BASE : $MY_BASE \n project : $project \n \
mainClazz : $mainClazz \
"

if [ "$project" = "" ]; then
    echo " please specify project at \$1 "
    exit
fi
if [ "$mainClazz" = "" ]; then
    echo " please specify main clazz file at \$2 "
    exit
fi

projectFolder=$MY_BASE/$project
if [ ! -d "$projectFolder" ]; then
    echo " project folder $projectFolder does not exists, please check that "
    exit
fi


EXISTS_PID=`jps -lvm | grep $mainClazz | grep -v grep | awk '{print $1}'`
if [ "$EXISTS_PID" = "" ]; then
    echo " the main class $mainClazz does not startup "
else
    kill -9 $EXISTS_PID
    echo " the main class $mainClazz shutdown succeed, kill -9 $EXISTS_PID "
fi

echo " shutdown end ... "

 

 

$appHome/startUp.sh 


../common/commandLineWrapperStartUp.sh $APP_NAME ./dev/conf/gen_idea_classpath.txt org.springframework.boot.loader.JarLauncher

 

$appHome/shutdown.sh 


../common/commandLineWrapperShutdown.sh $APP_NAME org.springframework.boot.loader.JarLauncher

 

$appHome/restart.sh 


# 1. shutdown
echo ""
./shutdown.sh

sleep 3s

# 2. startup
echo ""
./startUp.sh

 

$appHome/backup.sh 


bakDir="./dev/bak"
rm -rf $bakDir
mkdir -p $bakDir

echo " prepare copy files to /dev/bak "

cp *.properties $bakDir/ 2>/dev/null
echo " copied *.properties to $bakDir "
cp *.txt $bakDir/ 2>/dev/null
echo " copied *.txt to $bakDir "
cp *.jar $bakDir/ 2>/dev/null
echo " copied *.jar to $bakDir "
cp *.xml $bakDir/ 2>/dev/null
echo " copied *.xml to $bakDir "
cp *.sh $bakDir/ 2>/dev/null
echo " copied *.sh to $bakDir "

cp -r resources $bakDir/ 2>/dev/null
echo " copied /resources to $bakDir "

echo " copied files to /dev/bak "
echo ""
../common/backup.sh $APP_NAME org.springframework.boot.loader.JarLauncher


 

$appHome/release.sh 


mainJar="$APP_NAME-0.0.1.jar"
updatedMainJar="$APP_NAME-0.0.1.jar.0"

# 0. sanity check
# ifs update for filename with blank
echo ""
SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")

if [ ! -f "$updatedMainJar" ]; then
    echo " the newMainJar $updatedMainJar does not exists, please check that "
    exit
fi

# 1. backup first
./backup.sh

# 2. shutdown
echo ""
./shutdown.sh

# 3. release jar
echo ""
rm -rf $mainJar
echo " removed oldMainJar $mainJar "
move $updatedMainJar $mainJar
echo " rebuild $mainJar succeed "


sleep 3s

# 4. startup
echo ""
./startUp.sh


# restore ifs
IFS=$SAVED_IFS

 

新增一个项目, 需要拷贝一套 应用脚本, 然后需要调整一些配置 

        1. startUp.sh 需要调整 $APP_NAME, $classpathFIle, $mainClazz 

        2. shutdown.sh 需要调整 $APP_NAME, $mainClazz 

        3. restart.sh 不需要调整 

        4. backup.sh 需要调整 备份的业务, $APP_NAME, $mainClazz 

        5. release.sh 需要调整 $mainJar, $updatedMainJar, 发布的业务 

 

 

spring boot 的包包括了依赖, 应该怎么 更加轻量级的发布 ? 

这里的思路也很简单, 发布的服务器上面存放一份完整的 $springbootJar 的解压的版本 deflatedJar, 里面包含了 项目的 class, 配置文件, 依赖信息, spring 的代理信息 等等 

然后我们通过 maven 打包 spring boot 项目之后, 清理掉较大的 依赖 这部分 jar, 这时候 整个 jar 包就比较小了 

然后 上传到发布服务器, 然后 解压待发布的 jar, 覆盖 deflatedJar 里面的已有的内容, 然后再重新打 jar 包, 然后替换掉之前的 发布包, 然后启动服务即可 

 

主要是 release.sh 中的 发布的这一部分需要做一些调整 

# 3. release jar
echo ""
rm -rf $mainJar
echo " removed oldMainJar $mainJar "
# unzip -o -d deflatedJar/ $APP_NAME-0.0.1.jar.0
unzip -o -q -d deflatedJar/ $updatedMainJar
echo " deflated lastest jar into defaltedJar/ "
rm -rf $updatedMainJar
echo " removed updatedMainJar $updatedMainJar "
rm -rf deflatedJar/BOOT-INF/classes/application.yml
cp application.yml deflatedJar/BOOT-INF/classes/application.yml
echo " replace application.yml to BOOT-INF/classes/application.yml "
cd deflatedJar
# zip -r -0 ../$APP_NAME-0.0.1.jar .
zip -r -q -0 ../$mainJar .
cd .. 
echo " rebuild $mainJar succeed "

 

 

完 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1413933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Arduino开发实例-HTU21D温度和湿度传感器使用

HTU21D温度和湿度传感器使用 文章目录 HTU21D温度和湿度传感器使用1、HTU21D介绍2、硬件接线3、代码实现本文将详细介绍如何使用搭载来自瑞士 MEAS 的低成本、易于使用、高精度的HTU21D数字温度和湿度传感器模块。 1、HTU21D介绍 HTU21D传感器模块尺寸小,几乎可以安装在任何东…

MySQL连表操作之一对多

MySQL连表操作之一对多 目录 引入外键 Navicat创建外键使用外键SQL命令创建外键代码删除外键代码增加外键通过外键进行数据操作 正文 回到顶部 引入 当我们在数据库中创建表的时候,有可能某些列中值内容量很大,而且重复。 例子:创建一个…

磁盘挂载过程

硬盘 - 机械 HDD----便宜---这个,企业中更多- 固态 SSD----快SSD采用电子存储介质进行数据存储和读取的一种技术,突破了传统机械硬盘的性能瓶颈, 拥有极高的存储性能,被认为是存储技术发展的新星。 与传统硬盘相比,SSD…

系统架构演变

1.1系统架构的演变 2008年以后,国内互联网行业飞速发展,我们对软件系统的需求已经不再是过去”能用就行”这种很low的档次了,像抢红包、双十一这样的活动不断逼迫我们去突破软件系统的性能上限,传统的IT企业”能用就行”的开发思…

单片机设计_智能蓝牙电子秤(51单片机、HX711AD)

想要更多项目私wo!!! 一、电路设计 智能蓝牙电子称由51单片机、HX711AD称重模块、HC-05蓝牙模块、LCD1602等电路组成硬件部分,然后上传至APP。 二、运行结果 三、部分代码 #include "main.h" #include "HX711.h" #include "uart.h" #include …

【蓝桥杯冲冲冲】[NOIP2000 提高组] 方格取数

蓝桥杯备赛 | 洛谷做题打卡day19 文章目录 蓝桥杯备赛 | 洛谷做题打卡day19[NOIP2000 提高组] 方格取数题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题解代码我的一些话 [NOIP2000 提高组] 方格取数 题目背景 NOIP 2000 提高组 T4 题目描述 设有 N N…

已解决:安卓,怎么优雅接入科大讯飞语音评测功能?

写在前面: 网上关于讯飞接入的博客都很少,按说讯飞都是业界翘楚,不知为何,很少搜索到精品,一搜就是一个要求开会员的博客,我也是醉了。讯飞提供的文档也是不清晰,我是摸着石头过河,…

MySQL JSON数据类型全解析(JSON datatype and functions)

JSON(JavaScript Object Notation)是一种常见的信息交换格式,其简单易读且非常适合程序处理。MySQL从5.7版本开始支持JSON数据类型,本文对MySQL中JSON数据类型的使用进行一个总结。 目录 一、MySQL中的JSON 1.1 JSON数据格式 1.2 …

最长公共子串的问题(正常方法和矩阵法,动态规划)

题目: 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符…

Windows Qt C++ VTK 绘制三维曲线

Qt 自带数据可视化从文档上看,只能实现三维曲面。 QwtPlot3D在Qt6.6.0上没编译通过。 QCustomPlot 只能搞二维。 VTK~搞起。抄官网demo。 后续需求: 1、对数轴 2、Y轴逆序 3、Z轴值给色带,类似等高线图的色带 期待各位大佬多多指导。…

如何快速搭建实用的爬虫管理平台

目录 一、前言 二、选择合适的爬虫框架 三、搭建数据库 步骤1 步骤2 步骤3 四、搭建Web服务器 步骤1 步骤2 步骤3 步骤4 五、管理爬虫 六、总结 一、前言 爬虫是互联网数据采集的关键工具,但是随着数据量的增加和需求的多样化,手动运行和管…

超越传统,想修哪里就修哪里,SUPIR如何通过文本提示实现智能图像修复

项目简介 通过参数增加使得模型不仅能够修复图像中的错误或损坏,还能根据文本提示进行智能修复。例如根据描述来改变图像中的特定细节。这样的处理方式提升了图像修复的质量和智能度,使得模型能够更准确、更灵活地恢复和改进图像。 SUPIR的主要功能图像…

详解矩阵的LDU分解

目录 一. 矩阵分解 二. 解方程 三. 例题说明 四. 矩阵的LDU分解 五. 矩阵三角分解的唯一性 一. 矩阵分解 其实我们可以把一个线性系统(Linear System)看成两个三角系统(Triangular Systems),本文章将解释为什么可…

QT实现USB摄像头接入显示

一、UVC协议简介 UVC全称是USB Video Class(USB视频类),是一种标准化的USB视频设备通信协议,它定义了摄像头与主机之间的数据传输协议和格式。 UVC协议的出现,解决了摄像头厂商之间互不兼容,以及摄像头应…

2.Linux的例行性工 作(计划任务)

目录 1. 场景: 2. 单一执行的例行性任务--at(一次性) 2.1. 安装 2.2. at命令详解 2.2.1. 格式 2.2.2. 参数 2.2.3. 时间格式 2.2.4. 实验1 2.2.5. 实验2 2.2.6. 注意 2.2.7. at命令执行过程分析 2.2.8. 实验3 3. 循环执行的例行…

Elasticsearch:聊天机器人、人工智能和人力资源:电信公司和企业组织的成功组合

作者:来自 Elastic Jrgen Obermann, Piotr Kobziakowski 让我们来谈谈大型企业人力资源领域中一些很酷且改变游戏规则的东西:生成式 AI 和 Elastic Stack 的绝佳组合。 现在,想象一下大型电信公司的典型人力资源部门 — 他们正在处理一百万件…

mac/macos上编译electron源码

官方教程:Build Instructions | Electron 准备工作这里不写了,参考官方文档,还有上一篇windows编译electron electron源码下载及编译-CSDN博客 差不多步骤,直接来 网络记得使用魔法 下载编译步骤 0. 选择目录很重要&#xff0…

Emergent Abilities of Large Language Models 机翻mark

摘要 证明通过扩大语言模型可以可靠地提高性能和样本效率在广泛的下游任务。相反,本文讨论了我们称之为大型语言模型的新兴能力的一种不可预测的现象。我们认为如果一个能力不存在于较小的模型中,但在较大的模型中存在,则该能力就是新兴的。…

InforSuiteAS中创中间件windows环境部署

版本:InforSuiteAS_StE_V10.0.5.2.1 环境要求:Java环境 DK1.8版本, 内存2GB或以上 , 硬盘空间 10GB或以上, 监视器 图形界面安装需要256色以上,字符界面安装没有色彩要求 ,浏览器 Microsoft …

el-tree基础的树形节点设置节点不能选中高亮出来,对已经选中的节点设置disabled,对当前节点刚选中后设置禁用disabled

一、 el-tree基础的树形节点设置节点不能选中高亮出来 需求 我们使用element-ui或者element-plus的时候会遇到树形控件的使用,我们使用树形控件会限制有的节点不让选中和高亮出来,这个时候需要我们做限制。在实现中我们发现了element-ui和element-plus…