java实现接口代码启动win系统.exe程序,复制可用

controller,对外接口

package org.example.xxxxxx.processRestart.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.example.xxxx.processRestart.service.ProcessRestartService;
import org.example.xxxx.processRestart.vo.ProcessRestartReqVo;
import org.example.xxxx.util.ProcessOperationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 供远程调用
 */
@RestController
@RequestMapping("restartApi")
@RequiredArgsConstructor
@Log4j2
public class ProcessRestartController {

    private final ProcessRestartService service;

    /**
     * 远程重启程序接口
     * @return
     */
    @PostMapping("/executeRrestart")
    public ResponseEntity<Map<String, Object>> restartProcess(@RequestBody ProcessRestartReqVo model) {
        log.info("【远程重启程序】:{}", model);
        Map<String, Object> stringObjectMap = service.restartProcess(model);
        Map<String,Object> resMap = new HashMap<>();
        resMap.put("data",stringObjectMap);
        return ResponseEntity.ok(resMap);
    }

    public static void main(String[] args) {
        try {
            ProcessOperationUtil.killProcessByPort(20099);
            Thread.sleep(3000);
            ProcessOperationUtil.startExistingProcess("D:\\testexe\\testf1.exe");
            //ProcessOperationUtil.startExistingProcess("D:\\myProjectDemo\\nacos\\bin\\startup.cmd");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

ProcessRestartService 

public interface ProcessRestartService {

    public Map<String, Object> restartProcess(@RequestBody ProcessRestartReqVo model);
}




ProcessRestartServiceImpl ,实现类

package org.example.xxxxx.processRestart.service.impl;

import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j2;
import org.example.xxxx.processRestart.service.ProcessRestartService;
import org.example.xxxx.processRestart.vo.ProcessRestartReqVo;
import org.example.xxxx.util.ProcessOperationUtil;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 远程重启务实现类
 */
@Service
@Log4j2
public class ProcessRestartServiceImpl implements ProcessRestartService {

    @Override
    public Map<String, Object> restartProcess(ProcessRestartReqVo model) {
        Map<String,Object> result = new HashMap<>();

        try {
            // 1. 获取配置信息
            if (model.getPort() == null ||  model.getStartProgramPath()==null || model.getStartProgramPath()=="") {
                result.put("code", 400);
                result.put("msg", "无效的程序名称:" + model.getProcessName() + ",支持的端口或路径为空");
                return result;
            }
            // 2. 执行杀进程+重启操作
            ProcessOperationUtil.killProcessByPort(model.getPort());
            ProcessOperationUtil.startExistingProcess(model.getStartProgramPath());
            log.info("重启「" + model.getProcessName() + "」程序执行完成");
            // 3. 返回成功结果
            result.put("code", 200);
            result.put("msg", "成功:「" + model.getProcessName() + "」程序执行完成");
            return result;

        } catch (Exception e) {
            // 4. 返回异常结果
            result.put("code", 500);
            result.put("msg", "失败:「" + model.getProcessName() + "」重启异常,原因:" + e.getMessage());
            return result;
        }
    }

}

ProcessOperationUtil ,主要核心代码启用和杀死程序

package org.example.xxxxxx.util;

import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

/**
 * Windows进程操作工具类
 */
@Slf4j
@Component
public class ProcessOperationUtil {

    // 定义静态常量
    private static final File WINDOWS_NULL_DEVICE = new File("NUL");

    /**
     * Windows系统:根据端口号杀死占用进程(含子进程)
     * @param port 目标端口
     * @throws IOException 命令执行异常
     */
    public static void killProcessByPort(int port){
        try {
            // 查找占用端口的所有进程PID(包括非LISTENING状态,避免遗漏)
            String findPidCmd = String.format("netstat -ano | findstr \":%d\" | findstr \"LISTENING\"", port);
            String cmdResult = executeWindowsCommand(findPidCmd,5);
            log.info("停止服务-----{}",cmdResult);
            if (!cmdResult.isEmpty()) {
                String[] lines = cmdResult.split("\n");
                for (String line : lines) {
                    line = line.trim();
                    if (line.isEmpty()) {
                        continue;
                    }
                    String[] parts = line.split("\\s+");
                    if (parts.length >= 5) {
                        String pid = parts[4];
                        if (pid != null && !pid.trim().isEmpty() && !pid.equals("0")) {
                            // 杀死进程及其子进程(/T参数:终止进程和子进程;/F:强制终止)
                            String killCmd = String.format("taskkill /F /T /PID %s", pid.trim());
                            executeWindowsCommand(killCmd,5);
                            log.info("【杀进程】:端口{},PID={} 及其子进程已强制终止", port, pid);
                        }
                    }
                }
            } else {
                log.info("【杀进程】:端口{} 未被占用,无需终止进程", port);
            }
        } catch (Exception e) {
            log.error("【杀进程】:端口{} 终止进程失败,原因:{}", port, e.getMessage());
        }
    }

    /**
     * 启动程序
     * @param programPath 现有程序完整路径
     */
    public static void startExistingProcess(String programPath) throws IOException {
        ProcessBuilder pb = new ProcessBuilder();
        String wrappedPath = "\"" + programPath + "\"";

        if (programPath.endsWith(".bat") || programPath.endsWith(".cmd")) {
            pb.command("cmd.exe", "/c", "start", "\"\"", wrappedPath);
        } else {
            pb.command("cmd.exe", "/c", "start", "/B", "/MIN", "\"\"", wrappedPath);
        }

        pb.redirectInput(WINDOWS_NULL_DEVICE);
        pb.redirectOutput(WINDOWS_NULL_DEVICE);
        pb.redirectError(WINDOWS_NULL_DEVICE);

        File workDir = new File(programPath).getParentFile();
        if (workDir != null && workDir.exists()) {
            pb.directory(workDir);
        }

        Process process = pb.start();
        new Thread(() -> {
            try {
                process.getInputStream().close();
                process.getOutputStream().close();
                process.getErrorStream().close();
                process.waitFor(3, TimeUnit.SECONDS);
                int exitCode = process.waitFor();
                log.info("【启动程序】:启动命令执行完成,退出码:{}(0为成功)", exitCode);
          
            } catch (Exception ignored) {}
            process.destroy();
        }).start();
        log.info("【启动程序】{} 已后台执行", programPath);
    }

    public static void start(ProcessBuilder processBuilder) throws IOException{
        // 启动进程(非阻塞,不影响主进程)
        Process process = processBuilder.start();
        // 异步等待命令执行完成,不阻塞主线程,执行后释放句柄
        new Thread(() -> {
            try {
                // 显式关闭流
                process.getInputStream().close();
                process.getOutputStream().close();
                process.getErrorStream().close();

                int exitCode = process.waitFor();
                log.info("【启动程序】:启动命令执行完成,退出码:{}(0为成功)", exitCode);
           
            } catch (IOException  | InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("【启动程序】:命令执行中断 -> {}", e.getMessage());
            } finally {
                // 释放Process句柄,彻底解除与子进程的关联
                process.destroy();
            }
        }).start();
    }

    /**
     * 执行Windows系统命令并返回结果
     * @param cmd 命令内容
     * @return 命令执行结果
     * @throws IOException 执行异常
     */
    private static String executeWindowsCommand(String cmd, int timeoutSeconds) {
        StringBuilder result = new StringBuilder();
        try {
            Process process = new ProcessBuilder("cmd.exe", "/c", cmd)
                    .redirectErrorStream(true)
                    .start();

            // 异步读流,防止缓冲区满导致阻塞
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(process.getInputStream(), "GBK"))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        result.append(line).append("\n");
                    }
                } catch (IOException ignored) {}
            }).start();

            // 超时控制,最多等 timeoutSeconds 秒,强制结束
            boolean finished = process.waitFor(timeoutSeconds, TimeUnit.SECONDS);
            if (!finished) {
                process.destroy();
                log.warn("【命令超时】{} 已强制终止", cmd);
            }
        } catch (Exception e) {
            log.error("【命令执行失败】{}", cmd, e);
        }
        return result.toString().trim();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值