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

这篇具有很好参考价值的文章主要介绍了纯java的方式实现自定义自动化部署java项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

关于自动化部署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 session
            session = 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. 记录命令执行 log
            String line = null;
            while ((line = inputStreamReader.readLine()) != null) {
                System.out.println(line);
            }

            // 6. 记录命令执行错误 log
            String 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端口默认22
        int 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 session
            session = 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. 记录命令执行 log
            String line = null;
            while ((line = inputStreamReader.readLine()) != null) {
                System.out.println(line);
            }

            // 6. 记录命令执行错误 log
            String 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();
    }

}



文章来源地址https://www.toymoban.com/news/detail-410908.html

总结

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

到了这里,关于纯java的方式实现自定义自动化部署java项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Jenkins+Docker 实现一键自动化部署项目!步骤齐全,少走坑路

    大家好,我是互联网架构师! 本文章实现最简单全面的Jenkins+docker+springboot 一键自动部署项目,步骤齐全,少走坑路。 环境 :centos7+git(gitee) 简述实现步骤:在docker安装jenkins,配置jenkins基本信息,利用Dockerfile和shell脚本实现项目自动拉取打包并运行。 docker 安装社区版本CE

    2024年02月09日
    浏览(48)
  • github-action+docker实现项目可持续自动化部署

    这篇文章以部署vue3项目和nuxt2项目为例结合 github-action , docker , nginx 等介绍不同的项目自动部署流程 部署vue3项目 步骤: 1、腾讯云开启镜像仓库 2、github配置secrets 3、项目根目录创建dockerfile文件(在action工作流中创建镜像) 4、github配置action工作流(yml文件) 上面步骤执行结

    2024年04月26日
    浏览(43)
  • 前端项目自动化部署

    一、Git仓库管理项目 二、购买云服务器 三、搭建服务器环境(重点) 四、Jenkins进行自动化部署(重点) 提示:本地项目自动化部署流程,如下图 一、Git仓库管理项目 Git的安装和配置在这里就不做说明了 1、首先在Git仓库中创建一个仓库,用来保存本地项目,这里使用Git

    2024年02月15日
    浏览(49)
  • Jenkins自动化部署项目

    https://www.jenkins.io/ https://blog.csdn.net/qq_41581588/article/details/128687402 https://blog.csdn.net/zhishidi/article/details/118082509 https://blog.csdn.net/Sojou/article/details/125935262 使用心得

    2024年02月05日
    浏览(43)
  • Java实现自动化pdf打水印小项目 使用技术pdfbox、Documents4j

    博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。 博主所有博客文件目录索引:博客目录索引(持续更新) 视频平台:

    2024年02月20日
    浏览(74)
  • php项目自动化部署 —— Jenkins

    1.地址:Java Downloads | Oracle 因为我是在本地安装jenkins,这里用到的是java11-windows 2.安装JDK,并配置环境变量,csdn教程有很多 1.jenkins.msi 地址:Jenkins download and deployment,双击安装(傻瓜式) 2.安装完成以后,浏览器 并打开地址:localhost:8080 3.按照提示的路径输入密码 4.选择安

    2024年02月10日
    浏览(50)
  • 【OpenSSH+Jenkins搭建项目自动化部署】

    https://github.com/PowerShell/Win32-0penSSH/releases 下载最新的 OpenSSH安装包,如:openSSH-Win64.zip 将压缩包解压到 C:Program FilesOpenSSH 管理员运行cmd 进入目录C:Program FilesOpenSSH 执行命令 管理员运行cmd 进入目录C:Program FilesOpenSSH 执行命令 在当前用户的文件夹下会生成一对秘钥 将文件名

    2024年02月22日
    浏览(41)
  • docker+jenkins自动化部署springboot项目

    阿里云服务器1核2GB java 1.8.0._371 maven apache-maven3.8.8 git 1.8.3.1 docker和jenkins在一台服务器上,环境的配置,对于java和maven可以自己下载对应tar包进行配置,记得配置环境,也可以使用yum进行安装。记得配置/etc/profile后source一下: source /etc/profile Maven记得修改镜像!!! 在本地创建

    2024年02月03日
    浏览(49)
  • Docker 部署后端项目自动化脚本

    这里的项目位置是target同级目录 1.在项目下面新建一个bin目录 新建一个package.txt 写入下方代码后 后缀改为.bat 2.项目下新建一个deploy文件夹里面新建一个deploy.ps1脚本文件 示例 这里使用ssh 可以自己编写不太一样 上传到服务器中后自己选择一个合适的文件夹 然后旁边新建一个

    2024年02月01日
    浏览(53)
  • Jenkins结合gitee自动化部署SpringBoot项目

    安装教程 Gitee Plugin 源码管理 填写源码地址 注意: 请确保genkins所在的服务器有权限git拉取远程仓库代码,如果不可以请参考ssh配置 centos 配置ssh拉取远程git代码 源码管理 构建触发器 1.勾选Gitee webhook 触发构建 2.生成webhook密码 构建触发器   3.在gitee项目管理中配置webhook git

    2024年02月08日
    浏览(373)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包