java实现jar包的更新和发布

买了阿里云服务器,因为装的是win版本的;虽然每次发布jar包可以直接复制和启动;但是这个涉及到网络的问题,如果网络慢一点的话复制一个jar包进行需要好多分钟;于是就萌生了写一个网页实现更新jar包和启动jar包的渣渣网页;目前测试基本完成,就差优化界面和整合逻辑,基本的功能已经具备;主要分三部分完成。

                                                  (一)java关闭指定的端口号进程

本项目主要使用springboot实现,控制层实现调用killpid8081pid方法,实现指定端口号,因为我这边需要关闭的的是8081的端口进程,大家如果有需要的自行改造控制层就行;

    /**
     * 关闭指定的进程
     * @return
     */
    @ResponseBody
    @RequestMapping("killpid")
    public String killpid(){
        try {
            return   Skillservice.killpid8081pid("8081");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }

我新建了一个skillservice类,代码如下所示:

String[] split = pids.split(",");这个是获取多个端口号,可以实现多个进程号同时关闭,目前我这里只需要关闭8081端口;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class skillservice {
    public Set<Integer> ports;
    public String killpid8081pid(String pids) throws InterruptedException {
        JSONObject object=new JSONObject();

        String[] split = pids.split(",");
        Set<Integer> ports = new HashSet<>();
        for (String spid : split) {
            try{
                int pid = Integer.parseInt(spid);
                ports.add(pid);
            }catch(Exception e){

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                System.exit(0);
            }
        }

        skillservice kill = new skillservice();
        kill.ports = ports;
        System.out.println("need kill " + ports.size() + " num");
        for (Integer pid : ports) {
            kill.start(pid);
        }
        object.put("state","200");
        object.put("msg","清理完毕,程序即将退出");

        Thread.sleep(5000);
        System.exit(0);
        return object.toString();
    }
    public void start(int port){
        Runtime runtime = Runtime.getRuntime();
        try {
            //查找进程号
            Process p = runtime.exec("cmd /c netstat -ano | findstr \""+port+"\"");
            InputStream inputStream = p.getInputStream();
            List<String> read = read(inputStream, "UTF-8");
            if(read.size() == 0){
                System.out.println("找不到该端口的进程");
                try {
                    Thread.sleep(6000);
                    System.exit(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                for (String string : read) {
                    System.out.println(string);
                }
                System.out.println("找到"+read.size()+"个进程,正在准备清理");
                kill(read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 验证此行是否为指定的端口,因为 findstr命令会是把包含的找出来,例如查找80端口,但是会把8099查找出来
     * @param str
     * @return
     */
    private boolean validPort(String str){
        Pattern pattern = Pattern.compile("^ *[a-zA-Z]+ +\\S+");
        Matcher matcher = pattern.matcher(str);

        matcher.find();
        String find = matcher.group();
        int spstart = find.lastIndexOf(":");
        find = find.substring(spstart + 1);

        int port = 0;
        try {
            port = Integer.parseInt(find);
        } catch (NumberFormatException e) {
            System.out.println("查找到错误的端口:" + find);
            return false;
        }
        if(this.ports.contains(port)){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 更换为一个Set,去掉重复的pid值
     * @param data
     */
    public void kill(List<String> data){
        Set<Integer> pids = new HashSet<>();
        for (String line : data) {
            int offset = line.lastIndexOf(" ");
            String spid = line.substring(offset);
            spid = spid.replaceAll(" ", "");
            int pid = 0;
            try {
                pid = Integer.parseInt(spid);
            } catch (NumberFormatException e) {
                System.out.println("获取的进程号错误:" + spid);
            }
            pids.add(pid);
        }
        killWithPid(pids);
    }

    /**
     * 一次性杀除所有的端口
     * @param pids
     */
    public void killWithPid(Set<Integer> pids){
        for (Integer pid : pids) {
            try {
                Process process = Runtime.getRuntime().exec("taskkill /F /pid "+pid+"");
                InputStream inputStream = process.getInputStream();
                String txt = readTxt(inputStream, "GBK");
                System.out.println(txt);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    private List<String> read(InputStream in,String charset) throws IOException{
        List<String> data = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));
        String line;
        while((line = reader.readLine()) != null){
            boolean validPort = validPort(line);
            if(validPort){
                data.add(line);
            }
        }
        reader.close();
        return data;
    }
    public String readTxt(InputStream in,String charset) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));
        StringBuffer sb = new StringBuffer();
        String line;
        while((line = reader.readLine()) != null){
            sb.append(line);
        }
        reader.close();
        return sb.toString();
    }
}

这样就能实现关闭了指定的端口,更新jar包第一步实现;

                                             (二)上传jar包和bat文件

 

这里我使用的是freemaker模板,因为只是用来自己用,所以样式啥也还没进行调整,能上传就行:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传jar包</title>
</head>
<body>
<form action="review" method="POST" enctype="multipart/form-data">
    上传jar包: <input type="file" name="uploadpackage"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

这里需要注意的是:form标签需要增加enctype="multipart/form-data",系统才能识别我上传的其实是文件类型,控制层代码如下:

   /**
     * 接受jat包
     * @return
     */
    @RequestMapping("/review")
    @ResponseBody
    public String toreview(@RequestParam("uploadpackage") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }
        //获取上传的jar包名称
        String filename = file.getOriginalFilename();
        //判断指定的文件夹中是否存在该包
        File file0 = new File("C:\\app_log\\log");
        //获取文件夹下的所有的文件名称
        String[] fileName = file0.list();
        for (String name : fileName) {
            if (name.equals(filename)) {
                //说明该包已经存在,需要删除该包再提交
                File file1 = new File("C:\\app_log\\log\\" + name);
                // 路径为文件且不为空则进行删除
                if (file1.isFile() && file1.exists()) {
                    file1.delete();
//                    return "删除成功";
                }

            }
        }
//            String filePat h="C:\\package\\后台管理\\";
            String filePath = "C:\\app_log\\log\\";


            File dest = new File(filePath + filename);
            try {
                file.transferTo(dest);
                return "上传成功";

            } catch (Exception e) {
                return e.toString();
            }


        }

这样就实现了jar包的上传,如果之前有一样的jar,那么会先删除之后才上传,如果没有存在,那么就直接上传就行;

上传bat文件的也跟这个逻辑一样,代码如下,我就不讲解了:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传bat文件</title>
</head>
<body>
<form action="reviewbat" method="POST" enctype="multipart/form-data">
    上传bat文件: <input type="file" name="uploadbat"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

 

    @RequestMapping("/reviewbat")
    @ResponseBody
    public String toreview(@RequestParam("uploadbat") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }
        //获取上传的jar包名称
        String filename = file.getOriginalFilename();
        //判断指定的文件夹中是否存在该包
        File file0 = new File("C:\\app_log\\log");
        //获取文件夹下的所有的文件名称
        String[] fileName = file0.list();
        for (String name : fileName) {
            if (name.equals(filename)) {
                //说明该包已经存在,需要删除该包再提交
                File file1 = new File("C:\\app_log\\log\\" + name);
                // 路径为文件且不为空则进行删除
                if (file1.isFile() && file1.exists()) {
                    file1.delete();
//                    return "删除成功";
                }

            }
        }
//            String filePat h="C:\\package\\后台管理\\";
        String filePath = "C:\\app_log\\log\\";


        File dest = new File(filePath + filename);
        try {
            file.transferTo(dest);
            return "上传成功";

        } catch (Exception e) {
            return e.toString();
        }


    }

}

 

                                                              (三)使用bat启动jar包

第三部分也是本次的重点所在,我们上传了jar包之后,需要启动该项目,那我如果上去远程用命令行启动的话,那前面的过程就基本没有作用了,所以我们这里需要用java来启动bat文件

bat文件也就是上面的上传的文件,文件的内容就是启动刚刚上传的命令行:java -jar java -jar newsale-0.0.1-SNAPSHOT.jar

代码如下所示:

    /**
     * 实现自动化部署
     * @return
     */
    @RequestMapping("/bushu")
    @ResponseBody
    public String tobushu() {
        try {
            Runtime.getRuntime().exec("cmd /k start C:\\package\\tt.bat");
            return "success";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "success";

    }

这样就实现了通过网页上传jar包和上传bat文件,运行bat文件之后启动更新后的jar包,实现工程启动。欢迎指导交流。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值