- 目标
- 整体步骤
- Maven配置
- 1. 分离打包:配置打包、将依赖jar拷贝到外部
- 2. 编辑MANIFEST.MF
- 本地<=>服务器lib快速同步
- 1. 使用前提
- 2. 实现同步
- 每次部署只打包项目本身代码,这样部署会很快,因为包非常小。
- 对于依赖的jar包,只有在需要更新时(pom变动时)单独上传到服务器。
分为两步:
- 将项目代码和依赖包分开打包,每次只发布项目代码的jar(依赖Jenkins,或者手动拷贝到服务器中)
- 每次修改pom依赖后,通过脚本同步一次lib包中的jar到服务器
这一块比较简单,主要目的是为了将项目依赖的jar和项目本身代码分开打包
1. 分离打包:配置打包、将依赖jar拷贝到外部2. 编辑MANIFEST.MFmaven-compiler-plugin ${java.version} ${java.version} UTF-8 org.apache.maven.plugins maven-dependency-plugin copy-dependencies prepare-package copy-dependencies ${project.build.directory}/lib false false compile
这个文件在项目代码打完包的META-INF/MANIFEST.MF。作用是记录jar的Main入口类和所依赖的jar的位置。可以通过解压打完包的jar查看。
本地<=>服务器lib快速同步 1. 使用前提org.apache.maven.plugins maven-jar-plugin com.xxx.xxx.Application true lib/
- 使用物理服务器部署项目的同学,为了方便在开发阶段快速部署可以参考。
- 对于使用k8s等方式部署的项目,还得找运维同学配置。
- 这个方式主要是我自己开发阶段为了快速部署写的一点代码,主要是java实现。
所谓的快速同步,其实就是通过代码自动ssh到服务器上,获取服务器上的jar列表,和本地的jar列表进行比较,将新增的jar拷贝到服务器上,并将服务器上过期的jar删掉的过程。(这里使用Java,基于jsch实现,直接上代码)
- 首选引入依赖(因为我只在本地使用,所以scope配置成test)
com.jcraft jsch 0.1.54 test
- 代码实现
这个代码比较简单,我也做了注释,大家直接看一下吧。
【注意】:要本地自己先maven package打个包再运行以下代码上传
package sync_lib;
import cn.hutool.core.io.FileUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.util.*;
import java.util.stream.Collectors;
public class SyncLib {
private static Session session;
private static ChannelSftp channelSftp;
//只打印日志,不做上传删除操作(debug用)
private static final Boolean onlyPrint = true;
public static void main(String[] args) throws Exception {
//初始化ssh连接
initChannel();
try {
//cd 到服务器上的jar包所在目录
channelSftp.cd("服务器的lib目录(jar所在目录)");
//将jar目录下的jar都ls出来,保存到oldJarList中
Vector ls = channelSftp.ls(".");
List oldJarList = new ArrayList<>();
for (int i = 0; i < ls.size(); i++) {
ChannelSftp.LsEntry o = (ChannelSftp.LsEntry) ls.get(i);
String filename = o.getFilename();
if (filename.endsWith(".jar")) {
oldJarList.add(filename);
}
}
//这个是intellij idea中分离打包后的lib的路径, 大家可以直接改成自己本地的绝对路径
String newLibPath = SystemUtil.get(SystemUtil.USER_DIR) + "/target/lib/";
//获取本地最新jar的列表
List newLibList = FileUtil.listFileNames(newLibPath);
//对比新老jar列表,找出要新增的jar,删除的jar
List addJarList = addJarList(oldJarList, newLibList);
List removeJarList = removeJarList(oldJarList, newLibList);
//上传新增的jar
for (String addJarName : addJarList) {
if (onlyPrint) {
channelSftp.put(newLibPath + addJarName, addJarName);
}
System.out.println("add jar ==> " + addJarName);
}
//删除过期的jar
for (String removeJarName : removeJarList) {
if (onlyPrint) {
channelSftp.rm(removeJarName);
}
System.out.println("remove jar ==> " + removeJarName);
}
} finally {
//关闭ssh连接
closeChannel();
}
}
public static List removeJarList(List oldLibList, List newLibList) {
Set newLibSet = new HashSet<>(newLibList);
return oldLibList.stream().filter(item -> !newLibSet.contains(item)).collect(Collectors.toList());
}
public static List addJarList(List oldLibList, List newLibList) {
Set oldLigSet = new HashSet<>(oldLibList);
return newLibList.stream().filter(item -> !oldLigSet.contains(item)).collect(Collectors.toList());
}
public static void initChannel() throws JSchException {
//声明JSCH对象
JSch jSch = new JSch();
//获取一个Linux会话
session = jSch.getSession("root", "服务器IP", 22);
//设置登录密码
session.setPassword("服务器密码");
//关闭key的检验
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
session.setConfig(sshConfig);
//连接Linux
session.connect();
//通过sftp的方式连接
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
}
private static void closeChannel() {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}



