纯java的方式实现自定义自动化部署java项目

  • 前言
  • 使用第三方的服务或插件实现部署所存在的问题
  • 自动化部署java项目
    • java项目部署方式
      • 流程
    • 代码实现
      • 打包
      • 使用 java 执行 cmd 进行打包
      • 上传jar包到服务器指定路径
      • 远程执行Linux命令启动项目
      • main方法与完整代码
  • 总结

前言

关于自动化部署java项目的方案有很多,就比如说比较知名的使用 Jenkins 实现自动化部署,还有比如说使用 IDEA 中的插件 Alibaba Cloud Toolkit 实现自动化部署;其他的方式我也没太去了解,我现在要做的是使用java自定义部署项目

使用第三方的服务或插件实现部署所存在的问题

关于 Jenkins 我学习也使用了一会, Alibaba Cloud Toolkit 也试着用了一会,个人感觉用着有以下几点问题

1.Jenkins 安装及配置方面有点繁琐(对于小型项目来说没必要,对于大型的分布式项目来说会比较有用)
2.Jenkins 需要安装到服务器上,使用的时候会占用大量的服务器资源 (除非你专门给Jenkins配一个服务器或者装自己电脑上)
3.上手需要一定的时间,不同人熟悉需要的时间不同
4.因为这些东西并不是自己做的,没法完全按照自己的想法进行部署,遇到一些疑问解决起来比较麻烦耗时间

正因如此我就想能不能按照自己的项目部署方式来定制一套自动化部署的功能

自动化部署java项目

java项目部署方式

我的项目使用的是 spring boot,打包后也就只有2个jar包需要部署到服务器, 业务量决定了是否需要分布式

流程

1. maven 项目执行 clean 再 package 或者点击 IDEA 的 clean 再 package
2. 在 target 目录下找到需要部署的jar包上传至服务器 (同时备份这次上传的jar包)
3. 启动项目

代码实现

我直接将执行代码放在项目的 test 中执行

打包

mvn package 执行的时候默认会去调用 test 中的测试方法,为避免影响打包结果我选择了修改pom,当然了,你也可以选择修改打包命令
解决方法参考:https://blog.csdn.net/hjseo_seg/article/details/123657734

pom 中加入 或 修改以下代码
<plugin>  <groupId>org.apache.maven.plugin</groupId>  <artifactId>maven-compiler-plugin</artifactId>  <version>3.1</version>  <configuration>  <skip>true</skip>  </configuration>
</plugin>
<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-surefire-plugin</artifactId>  <version>2.5</version>  <configuration>  <skip>true</skip>  </configuration>
</plugin>
或者修改打包命令为
mvn package -Dmaven.test.skip=true

使用 java 执行 cmd 进行打包

java执行cmd参考:https://blog.csdn.net/weixin_43916074/article/details/123118256

执行 cmd 命令时内容前需要加 cmd /c
例如原 cmd 命令:mvn package
修改后 cmd 命令:cmd /c mvn package

/*** 执行cmd命令* @param cmd cmd命令*/public static void cmd(String cmd) {Runtime run = Runtime.getRuntime();try {Process p = run.exec(cmd);InputStream ins = p.getInputStream();new Thread(() -> {String line = null;byte[] b = new byte[1024];int num = 0;try {while ((num = ins.read(b)) != -1) {System.out.print(byteToStr(b));}} catch (Exception e) {e.printStackTrace();}}).start();p.waitFor();} catch (Exception e) {e.printStackTrace();}}public static String byteToStr(byte[] buffer) {try {int length = 0;for (int i = 0; i < buffer.length; ++i) {if (buffer[i] == 0) {length = i;break;}}return new String(buffer, 0, length, "gb2312");} catch (Exception e) {return "";}}

上传jar包到服务器指定路径

java实现上传文件到服务器参考自:http://t.zoukankan.com/kuangzhisen-p-8662816.html

先在pom中加入相关依赖
<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.51</version>
</dependency>
java实现使用ssh上传文件到Linux服务器

这里我就直接以用户名密码的方式进行连接,如果要通过其他方式登录那就需要自己再稍微改一下了

/*** 上传文件到服务器* @param host       主机地址* @param port       ssh端口* @param username   用户名* @param password   密码* @param localFile  本地文件* @param serverPath 上传到服务器的路径* @throws Exception*/public static void sshSftp(String host, int port, String username, String password, String localFile, String serverPath)throws Exception {Session session = null;ChannelSftp channel = null;JSch jsch = new JSch();if (port <= 0) {//连接服务器,采用默认端口session = jsch.getSession(username, host);} else {//采用指定的端口连接服务器session = jsch.getSession(username, host, port);}//如果服务器连接不上,则抛出异常if (session == null) {throw new Exception("session is null");}//设置第一次登陆的时候提示,可选值:(ask | yes | no)session.setConfig("StrictHostKeyChecking", "no");// 如果出现了 com.jcraft.jsch.JSchException: Algorithm negotiation fail ,就加入下面这条// session.setConfig("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256");//设置登陆主机的密码session.setPassword(password);//设置密码//设置登陆超时时间session.connect();try {//创建sftp通信通道channel = (ChannelSftp) session.openChannel("sftp");channel.connect(1000);ChannelSftp sftp = (ChannelSftp) channel;//进入服务器指定的文件夹sftp.cd(serverPath);//列出服务器指定的文件列表for (Object o : sftp.ls("*")) {System.out.println(o);}//以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换以下流就可以了File file = new File(localFile);OutputStream outstream = sftp.put(file.getName());InputStream instream = new FileInputStream(file);byte[] b = new byte[1024];int n;while ((n = instream.read(b)) != -1) {outstream.write(b, 0, n);}outstream.flush();outstream.close();instream.close();} catch (Exception e) {e.printStackTrace();} finally {session.disconnect();if (channel != null) {channel.disconnect();}}}

远程执行Linux命令启动项目

java实现远程执行Linux参考自:https://blog.csdn.net/qq_16504067/article/details/103471898

这里我就直接以用户名密码的方式进行连接,如果要通过其他方式登录那就需要自己再稍微改一下了
默认执行单条命令,如要执行多条命令可在每条命令结尾加 \n 表示换行执行下条命令,
例如:“pwd \n” + “cd /app/server \n” + “pwd”

    /*** 远程执行Linux命令* @param host     主机地址* @param port     端口* @param username 用户名* @param password 密码* @param sh       执行内容*/public static void shell(String host, int port, String username, String password, String sh) {JSch jSch = new JSch();Session session = null;ChannelExec channelExec = null;BufferedReader inputStreamReader = null;BufferedReader errInputStreamReader = null;try {// 1. 获取 ssh sessionsession = jSch.getSession(username, host, port);session.setPassword(password);session.setTimeout(3000);session.setConfig("StrictHostKeyChecking", "no");// 如果出现了 com.jcraft.jsch.JSchException: Algorithm negotiation fail ,就加入下面这条//session.setConfig("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256");session.connect();  // 获取到 ssh session// 2. 通过 exec 方式执行 shell 命令channelExec = (ChannelExec) session.openChannel("exec");channelExec.setCommand(sh);channelExec.connect();  // 执行命令// 3. 获取标准输入流inputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()));// 4. 获取标准错误输入流errInputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getErrStream()));// 5. 记录命令执行 logString line = null;while ((line = inputStreamReader.readLine()) != null) {System.out.println(line);}// 6. 记录命令执行错误 logString errLine = null;while ((errLine = errInputStreamReader.readLine()) != null) {System.err.println(errLine);}} catch (Exception e) {e.printStackTrace();} finally {try {if (inputStreamReader != null) {inputStreamReader.close();}if (errInputStreamReader != null) {errInputStreamReader.close();}if (channelExec != null) {channelExec.disconnect();}if (session != null) {session.disconnect();}} catch (IOException e) {e.printStackTrace();}}}

main方法与完整代码

首先执行 cmd 命令 mvn clean 与 mvn package,再设置本地的jar包路径上传jar包,执行相关命令,例如我每次部署都习惯先备份一遍今天的jar包,最后执行事先准备好的shell脚本启动项目

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @Author: asus* @Date: 1919/8/10 11:45:14*/
public class ReleasePackage {public static void main(String[] args) {long start = System.currentTimeMillis();// 打包long s = System.currentTimeMillis();System.out.println("==================== 清理 ====================");cmd("cmd /c mvn clean");System.out.println("清理耗时:" + (System.currentTimeMillis() - s) + "ms");s = System.currentTimeMillis();System.out.println("==================== 打包 ====================");cmd("cmd /c mvn package");System.out.println("打包耗时:" + (System.currentTimeMillis() - s) + "ms");// 服务器地址String host = "11.4.5.14";// ssh端口默认22int port = 24;// 用户名String username = "1919";// 密码String password = "1145141919810";// 上传文件到服务器try {s = System.currentTimeMillis();String localFile = "C:\\ho\\admin\\target\\admin.jar";String serverPath = "/app/ho";System.out.println("上传 " + localFile + " 到 " + serverPath);sshSftp(host, port, username, password, localFile, serverPath);System.out.println(localFile + "=== 上传完成 ===");System.out.println("上传文件1耗时:" + (System.currentTimeMillis() - s) + "ms");s = System.currentTimeMillis();localFile = "C:\\ho\\user\\target\\user.jar";System.out.println("上传 " + localFile + " 到 " + serverPath);sshSftp(host, port, username, password, localFile, serverPath);System.out.println(localFile + "=== 上传完成 ===");System.out.println("上传文件2耗时:" + (System.currentTimeMillis() - s) + "ms");// 备份jar包并启动项目s = System.currentTimeMillis();System.out.println("===== 开始启动 =====");String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());String sh = "cd /app/ho \n" +"mkdir /app/ho/backup/" + date + "\n" +"\\cp admin.jar backup/" + date + "/\n" +"\\cp user.jar backup/" + date + "/\n" +"/app/ho/run.sh \n";shell(host, port, username, password, sh);System.out.println("===== 操作完成 =====");System.out.println("命令执行耗时:" + (System.currentTimeMillis() - s) + "ms");} catch (Exception e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("操作总耗时:" + ((end - start) / 1000) + "s" + ((end - start) % 1000) + "ms");}/*** 执行cmd命令* 参考自 https://blog.csdn.net/weixin_43916074/article/details/123118256** @param cmd cmd命令*/public static void cmd(String cmd) {Runtime run = Runtime.getRuntime();try {Process p = run.exec(cmd);InputStream ins = p.getInputStream();new Thread(() -> {String line = null;byte[] b = new byte[1024];int num = 0;try {while ((num = ins.read(b)) != -1) {System.out.print(byteToStr(b));}} catch (Exception e) {e.printStackTrace();}}).start();p.waitFor();} catch (Exception e) {e.printStackTrace();}}/*** 远程执行Linux命令* 参考自 https://blog.csdn.net/qq_16504067/article/details/103471898** @param host     主机地址* @param port     端口* @param username 用户名* @param password 密码* @param sh       执行内容*/public static void shell(String host, int port, String username, String password, String sh) {JSch jSch = new JSch();Session session = null;ChannelExec channelExec = null;BufferedReader inputStreamReader = null;BufferedReader errInputStreamReader = null;try {// 1. 获取 ssh sessionsession = jSch.getSession(username, host, port);session.setPassword(password);session.setTimeout(3000);session.setConfig("StrictHostKeyChecking", "no");// 如果出现了 com.jcraft.jsch.JSchException: Algorithm negotiation fail ,就加入下面这条// session.setConfig("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256");session.connect();  // 获取到 ssh session// 2. 通过 exec 方式执行 shell 命令channelExec = (ChannelExec) session.openChannel("exec");channelExec.setCommand(sh);channelExec.connect();  // 执行命令// 3. 获取标准输入流inputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()));// 4. 获取标准错误输入流errInputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getErrStream()));// 5. 记录命令执行 logString line = null;while ((line = inputStreamReader.readLine()) != null) {System.out.println(line);}// 6. 记录命令执行错误 logString errLine = null;while ((errLine = errInputStreamReader.readLine()) != null) {System.err.println(errLine);}} catch (Exception e) {e.printStackTrace();} finally {try {if (inputStreamReader != null) {inputStreamReader.close();}if (errInputStreamReader != null) {errInputStreamReader.close();}if (channelExec != null) {channelExec.disconnect();}if (session != null) {session.disconnect();}} catch (IOException e) {e.printStackTrace();}}}/*** 上传文件到服务器* 参考自 http://t.zoukankan.com/kuangzhisen-p-8662816.html** @param host       主机地址* @param port       ssh端口* @param username   用户名* @param password   密码* @param localFile  本地文件* @param serverPath 上传到服务器的路径* @throws Exception*/public static void sshSftp(String host, int port, String username, String password, String localFile, String serverPath)throws Exception {Session session = null;ChannelSftp channel = null;JSch jsch = new JSch();if (port <= 0) {//连接服务器,采用默认端口session = jsch.getSession(username, host);} else {//采用指定的端口连接服务器session = jsch.getSession(username, host, port);}//如果服务器连接不上,则抛出异常if (session == null) {throw new Exception("session is null");}//设置第一次登陆的时候提示,可选值:(ask | yes | no)session.setConfig("StrictHostKeyChecking", "no");// 如果出现了 com.jcraft.jsch.JSchException: Algorithm negotiation fail ,就加入下面这条// session.setConfig("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256");//设置登陆主机的密码session.setPassword(password);//设置密码//设置登陆超时时间session.connect();try {//创建sftp通信通道channel = (ChannelSftp) session.openChannel("sftp");channel.connect(1000);ChannelSftp sftp = (ChannelSftp) channel;//进入服务器指定的文件夹sftp.cd(serverPath);//列出服务器指定的文件列表for (Object o : sftp.ls("*")) {System.out.println(o);}//以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换以下流就可以了File file = new File(localFile);OutputStream outstream = sftp.put(file.getName());InputStream instream = new FileInputStream(file);byte[] b = new byte[1024];int n;totalLength = file.length();finishLength = 0;startProcess();while ((n = instream.read(b)) != -1) {outstream.write(b, 0, n);finishLength += 1024;}pd.join();outstream.flush();outstream.close();instream.close();} catch (Exception e) {e.printStackTrace();} finally {session.disconnect();if (channel != null) {channel.disconnect();}}}private static String byteToStr(byte[] buffer) {try {int length = 0;for (int i = 0; i < buffer.length; ++i) {if (buffer[i] == 0) {length = i;break;}}return new String(buffer, 0, length, "gb2312");} catch (Exception e) {return "";}}private static Thread pd = new Thread();private static long totalLength = 0L;private static long finishLength = 0L;private static void startProcess() {pd = new Thread(() -> {while (finishLength < totalLength) {System.out.print(getProcess(totalLength, finishLength));try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getProcess(totalLength, finishLength));});pd.start();}private static String getProcess(long total, long finish) {StringBuilder str = new StringBuilder();str.append("\r上传中[");int finishP = finish < total ? (int) (finish * 100 / total) : 100;for (int i = 0; i < 100; i++) {if (i > finishP) {str.append("-");} else if (i == finishP) {str.append(">");} else {str.append("=");}}str.append("]").append(finishP).append("%");return str.toString();}}

总结

这样就可以通过使用 java 的一个 main 方法进行自动化部署,实现了打包在本地部署自动化的想法,不需要熟悉额外的部署服务,本方法非常适合小型项目的部署,而且可以根据自己的需求在这基础上进行定制

纯java的方式实现自定义自动化部署java项目相关推荐

  1. Jenkins自动化部署Vue项目

    Jenkins自动化部署Vue项目 jenkins介绍 Jenkins是开源的,使用Java编写的持续集成的工具,在Centos上可以通过yum命令行直接安装.Jenkins只是一个平台,真正运作的都 ...

  2. (三)jenkins+bonobo git server+windows系统自动化部署springboot项目(远程windows自动化部署)

    前提 jenkins安装,参考:(一)jenkins+bonobo git server+windows系统自动化部署springboot项目(jenkins安装) 自动化部署,参考:(二)jenki ...

  3. (二)jenkins+bonobo git server+windows系统自动化部署springboot项目(自动化部署)

    前提:jenkins安装 参考:(一)jenkins+bonobo git server+windows系统自动化部署springboot项目(jenkins安装) 1插件下载 主要是检查如下插件是否 ...

  4. Jenkins结合Gitee(码云)自动化部署Springboot项目(比较详细)

    Jenkins结合码云自动化部署Springboot项目 一.准备工作(有的话,可以忽略) 1. 安装wget 2. 安装jdk 3. 安装maven 4. 安装git 二.开始部署 (jenkins ...

  5. 《阿里云服务器搭建》------实现Jenkins和github之间自动化部署Java web项目

    本系列教程的搭建环境为阿里云服务器,其他服务器可作为参考. 本文主要讲述实现Jenkins和github之间自动化部署项目 在浏览器中打开我们的jenkins页面.(http://ip:80/jenk ...

  6. 利用Jenkins自动化部署springboot项目到阿里云服务器(centos8)

    背景: 最近想部署一个springboot项目到阿里云服务器里面.捣鼓了很久,构建了很多次,都失败了!实在是一脸辛酸,有点气馁~ 在此想记录一下构建的过程. 不了解Jenkins之前,觉得Jenkin ...

  7. Jenkins自动化部署-配置项目(下)

    一.新建项目,设置Git地址,账号密码. 多种方式,ssh方式,需要配置私钥. 第1个错误:Git没安装 Linux机器上,先安装Git软件. CentOs系统,yum install git git ...

  8. Diango博客--18.使用 Fabric 自动化部署 Django 项目

    文章目录 1.本地安装 Fabric 2.部署过程回顾 3.完善项目配置 4.修改 BASE_DIR 配置项 5.设置 Supervisor 环境变量 6.编写 Fabric 脚本 7.执行 Fabr ...

  9. 使用 Fabric 自动化部署 Django 项目

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在上一篇教程中,我们通过手工方式将代码部署到了服务器.整个过程涉及到十几条命令,输了 ...

最新文章

  1. Java正则入门(1)——去除字符串头尾空格
  2. 概要设计阶段--组装测试计划
  3. Android中AIDL的使用详解
  4. 家里用服务器放在哪个位置,路由器摆放在家中哪个位置好 路由器摆放位置【详解】...
  5. boost::adjacency_matrix用法的测试程序
  6. strtok函数取WinMain的参数
  7. Find Minimum in Rotated Sorted Array
  8. oracle中修改数据库实例监听的ip和端口
  9. 平面设计学习社区,让你的作品展示出来
  10. 2021年SWPUACM暑假集训day4KMP算法
  11. 手把手教你搭建Java 开发环境
  12. mcgs组态软件中字体如果从左到右变化_在MCGS嵌入版组态软件中,可以利用大小变化来实现动画效果。( )...
  13. SAP培训及ABAP学习入门必读
  14. 服务器的tpmc查询网站,xxxx最新服务器选型指标_tpcc(tpmc)标准值_tpc官方整理.pdf
  15. 计算机键盘的认识 功能,笔记本电脑键盘的功能_笔记本电脑键盘的认识
  16. R语言中插补缺失值的R包simputation
  17. 零基础做一个微信答题小程序(三)
  18. 怀孕用计算机来算周期怎么算,怀孕周期计算器公式
  19. NXP S32K146 FLEXI2C底层驱动+IAM-20680(二)
  20. CodeForces 3B Lorry 贪心

热门文章

  1. ubuntu16.04下qt5.14报错:/home/XXXXX/Qt5.14.1/5.14.1/gcc_64/include/QtGui/qopengl.h:141: error: GL/
  2. php中md5加密函数怎么用,PHP加密函数—md5()函数加密实例用法
  3. 与爱同行,育润走进贫困家庭,助推公益事业
  4. css:使用div绘制一条竖线
  5. AES - Openssl AES 函数说明
  6. atan2(a,b)和atan的区别
  7. 如何快速推广引流?利用微博截流疯狂获取流量
  8. 排序算法之简单插入排序法
  9. 计算机内存条属于组合电路吗,寄存器和内存条的基础实现电路方案
  10. EditPlus安装Json格式化工具功能