如何在Spring Shell中获取上一条命令输出以实现自定义命令逻辑?
在Spring Shell中读取上一条命令输出的实现方案
Spring Shell本身没有内置读取上一条命令输出的能力,需要通过自定义组件实现输出拦截和存储,以下是具体步骤:
1. 实现输出存储的单例Bean
创建一个全局可访问的存储Bean,用来保存上一条命令的输出内容:
@Component public class LastCommandOutputStorage { private String lastOutput; public String getLastOutput() { return lastOutput; } public void setLastOutput(String lastOutput) { this.lastOutput = lastOutput; } }
2. 自定义输出拦截器
继承Spring Shell的默认结果处理器,拦截命令的正常输出和错误输出,并存入存储Bean:
@Component public class StoringResultHandler extends DefaultResultHandler { private final LastCommandOutputStorage storage; public StoringResultHandler(ResultHandlerConfigurer configurer, LastCommandOutputStorage storage) { super(configurer); this.storage = storage; } @Override public void handleResult(Object result) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream originalOut = System.out; System.setOut(new PrintStream(baos)); try { super.handleResult(result); storage.setLastOutput(baos.toString()); } finally { System.setOut(originalOut); } } @Override public void handleError(Throwable error) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream originalErr = System.err; System.setErr(new PrintStream(baos)); try { super.handleError(error); storage.setLastOutput(baos.toString()); } finally { System.setErr(originalErr); } } }
3. 封装外部系统命令(如cat、javac)
如果要捕获cat、javac这类外部命令的输出,需要在Spring Shell中封装这些命令,通过ProcessBuilder执行并捕获输出:
@ShellComponent public class SystemCommandWrapper { private final LastCommandOutputStorage storage; public SystemCommandWrapper(LastCommandOutputStorage storage) { this.storage = storage; } @ShellMethod(key = "cat", value = "执行cat命令") public String cat(String filePath) { try { Process process = new ProcessBuilder("cat", filePath).start(); String output = new String(process.getInputStream().readAllBytes()); String error = new String(process.getErrorStream().readAllBytes()); String fullOutput = output + error; storage.setLastOutput(fullOutput); return fullOutput; } catch (IOException e) { String errorMsg = "执行cat命令失败:" + e.getMessage(); storage.setLastOutput(errorMsg); return errorMsg; } } @ShellMethod(key = "javac", value = "执行javac编译命令") public String javac(String javaFile) { try { Process process = new ProcessBuilder("javac", javaFile).start(); String output = new String(process.getInputStream().readAllBytes()); String error = new String(process.getErrorStream().readAllBytes()); String fullOutput = output + error; storage.setLastOutput(fullOutput); return fullOutput; } catch (IOException e) { String errorMsg = "执行javac命令失败:" + e.getMessage(); storage.setLastOutput(errorMsg); return errorMsg; } } }
4. 实现自定义solve命令
注入存储Bean,读取上一条命令的输出并生成对应解决方案:
@ShellComponent public class CmdzenCommands { private final LastCommandOutputStorage storage; public CmdzenCommands(LastCommandOutputStorage storage) { this.storage = storage; } @ShellMethod(key = "cmdzen solve", value = "根据上一条命令输出提供解决方案") public String solve() { String lastOutput = storage.getLastOutput(); if (lastOutput == null || lastOutput.isEmpty()) { return "没有找到上一条命令的输出"; } if (lastOutput.contains("No such file or directory")) { return "解决方案:检查文件路径是否正确,或创建缺失文件:`touch hi.txt`"; } else if (lastOutput.contains("non-static method cannot be referenced from a static context")) { return "解决方案:将`hi()`改为静态方法,或创建类实例后调用:\n" + "```java\n" + "new YourClass().hi();\n" + "```"; } else { return "无法识别当前输出类型"; } } }
内容的提问来源于stack exchange,提问作者swaruph
相关产品推荐
相关产品推荐

