Java 11+Spring环境下执行部分curl命令返回空输入流问题
问题根因
Runtime.getRuntime.exec(String command)不会像系统shell一样自动处理命令中的单引号语义。你在命令中给URL、Header加的单引号,会被直接作为参数值的一部分传递给curl,导致curl实际请求的是带单引号的错误URL,发送的是格式错误的Auth头,服务端返回错误,自然没有正常响应。- 你只读取了进程的标准输入流
getInputStream(),如果curl执行出错,错误信息会输出到标准错误流getErrorStream(),这时候你读输入流就会得到空内容,看不到具体错误。 - 没有等待curl进程执行完成就直接读取流,可能出现流还没输出就被读取的异常。
为什么第一个测试curl能正常执行
第一个测试curl的参数没有用单引号包裹,exec拆分参数的时候没有产生歧义,所以可以正常执行。
解决方案
方案1:改用数组形式传递exec参数(推荐)
把curl命令的每个参数拆分为独立的字符串元素,不需要加额外的引号,示例代码如下:
// 拆分所有参数,不需要额外加单引号 String[] cmdGetDocId = new String[]{ "curl", "--location", "--request", "GET", "http://xxx.xx.xx.xx:8080/document/details/", "--header", "Authorization: Basic xxxxx" }; Process process = Runtime.getRuntime().exec(cmdGetDocId); // 等待进程执行完成 int exitCode = process.waitFor(); if (exitCode == 0) { // 正常执行,读输入流 InputStream inputStream = process.getInputStream(); JSONObject json = convertToJSON(inputStream); } else { // 执行出错,读错误流排查问题 InputStream errorStream = process.getErrorStream(); // 打印错误流内容即可定位具体报错 }
方案2:Spring环境原生Http调用替代curl(更推荐)
Java Spring环境完全不需要依赖外部curl命令发送Http请求,直接使用内置的RestTemplate或者WebClient即可,跨平台且性能更高,示例代码:
// RestTemplate 示例 RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Basic xxxxx"); HttpEntity<Void> request = new HttpEntity<>(headers); ResponseEntity<JSONObject> response = restTemplate.exchange( "http://xxx.xx.xx.xx:8080/document/details/", HttpMethod.GET, request, JSONObject.class ); JSONObject json = response.getBody();
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

