Java执行外部程序(Apache Commons Exec)

原创 2015年07月07日 11:58:59

之前使用Runtime.getRuntime().exec调用外部程序,在Tomcat下会有当前线程一直等待的现象。当时为了解决这个问题,使用新建线程接收外部程序的输出信息,详情请看博客http://blog.csdn.net/accountwcx/article/details/46785437


后来在网上找到开源的Java调用外部程序类库Apache Commons Exce,这个类库提供非阻塞方法调用外部程序。

官方网址 http://commons.apache.org/proper/commons-exec/

maven地址 http://mvnrepository.com/artifact/org.apache.commons/commons-exec/1.3

官方教程 http://commons.apache.org/proper/commons-exec/tutorial.html 官方教程提供的非阻塞方法在1.3版中不适用


Commons Exec对调用外部程序进行了封装,只需要少量代码即可实现外部程序调用,如执行命令"AcroRd32.exe /p /h c:\help.pdf"。

String line = "AcroRd32.exe /p /h c:\help.pdf";
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();

//设置命令执行退出值为1,如果命令成功执行并且没有错误,则返回1
executor.setExitValue(1);

int exitValue = executor.execute(cmdLine);

Commons Exec支持通过添加参数方式构建命令,执行命令"AcroRd32.exe /p /h c:\help.pdf"也可以按如下方法创建。

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
cmdLine.addArgument("/h");

Map map = new HashMap();
map.put("file", new File("c:\help.pdf"));
cmdLine.addArgument("${file}");
cmdLine.setSubstitutionMap(map);

DefaultExecutor executor = new DefaultExecutor();
executor.setExitValue(1);
int exitValue = executor.execute(cmdLine);

Commons Exec支持设置外部命令执行等待时间,如果超过等等时间则中断执行。

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
cmdLine.addArgument("/h");

Map map = new HashMap();
map.put("file", new File("c:\help.pdf"));
cmdLine.addArgument("${file}");
cmdLine.setSubstitutionMap(map);

DefaultExecutor executor = new DefaultExecutor();

//创建监控时间60秒,超过60秒则中端执行
ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
executor.setWatchdog(watchdog);

executor.setExitValue(1);
int exitValue = executor.execute(cmdLine);

上面的执行外部命令都是阻塞式,也就是在执行外部命令时,当前线程是阻塞的。如果不想在执行外部命令的时候,把当前线程阻塞,可以使用DefaultExecuteResultHandler处理外部命令执行的结果,释放当前线程。

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
cmdLine.addArgument("/h");

Map map = new HashMap();
map.put("file", new File("c:\help.pdf"));
cmdLine.addArgument("${file}");
cmdLine.setSubstitutionMap(map);

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
DefaultExecutor executor = new DefaultExecutor();
executor.setExitValue(1);
executor.execute(cmdLine, resultHandler);
resultHandler.waitFor();


博客http://blog.csdn.net/accountwcx/article/details/46785437的HtmlToPdf类可以改成如下。

import java.io.File;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;

public class HtmlToPdf {
	//wkhtmltopdf在系统中的路径
	private static final String toPdfTool = "c:\\wkhtmltopdf.exe";
	
	/**
	 * @param srcPath html路径,可以本地硬盘路径或者url
	 * @param destPath pdf保存路径
	 * @return 转换成功返回true
	 */
	public static boolean convert(String srcPath, String destPath){		
		File file = new File(destPath);
		File parent = file.getParentFile();
		//如果pdf保存路径不存在,则创建路径
		if(!parent.exists()){
			parent.mkdirs();
		}
		
		CommandLine cmdLine = new CommandLine(toPdfTool);
		cmdLine.addArgument(srcPath, true);
		cmdLine.addArgument(destPath, true);
		
		DefaultExecutor executor = new DefaultExecutor();
		
		//设置执行命令成功的退出值为1
		executor.setExitValue(1);
		
		//非阻塞
		DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
		
		boolean result = true;
		try {
			executor.execute(cmdLine, resultHandler);
			resultHandler.waitFor();
		} catch (Exception e) {
			result = false;
			e.printStackTrace();
		}
		
		return result;
	}
}



使用Apache Commons Exec管理进程

网上竟然搜不到详细一点的帖子,估计大家用JAVA去管理进程的场景比较少吧,只好自己总结一个。Java管理进程,API级别是使用:Runtime.getRuntime().exec(“shell”); ...
  • fd_mas
  • fd_mas
  • 2015年12月02日 14:21
  • 2861

利用Apache Commons Exec调用命令行并取得命令行的输出(实例)

public String ping(String ip) { try { String command = "ping "+ip; ...
  • ligaoyang
  • ligaoyang
  • 2012年09月28日 16:21
  • 10928

common-exec调用进程命令

package org.sf.exec; import java.io.File; import java.io.IOException; import java.util.HashMap;...
  • xunianchong
  • xunianchong
  • 2015年03月19日 13:59
  • 1156

Android AsyncTask 分析内部实现

sdk3.0前,使用内部的线程池,多线程并发执行。线程池大小等于5,最大达128 sdk3.0后,使用默认的serial线程池,执行完一个线程,再顺序执行下一个线程。sdk4.3时 线程池大小等于5,...
  • jjwwmlp456
  • jjwwmlp456
  • 2014年08月17日 00:34
  • 3226

MyBATIS原理第三篇: SqlSession下的四大对象之一——执行器(executor)

首先我先解释一下标题 四大对象是指:executor, statementHandler,parameterHandler,resultHandler对象。(为了方便下面的文章说道四大对象就专指它们)...
  • ykzhen2015
  • ykzhen2015
  • 2015年12月15日 14:26
  • 6867

关于mybatis里面的Executor

使用mybatis查寻数据,跟踪其执行流程 最开始执行的语句 this.getSqlSession().selectList("QUERY-QUESTION", data, rowBounds...
  • w_intercool
  • w_intercool
  • 2012年08月21日 22:07
  • 12941

Apache commons exec 简介和简单ping命令方法调用实现

Apache commonsexec提供一些常用的方法用来执行外部进程。Apache commons exec库提供了监视狗Watchdog来设监视进程的执行超时,同时也还实现了同步和异步功能。 A...
  • ffm83
  • ffm83
  • 2014年12月30日 15:09
  • 1668

Apache common exec包的相应使用总结

最近在写一个Java工具,其中调用了各种SHELL命令,使用了Runtime.getRuntime().exec(command);这个方法。但是在我调用某个命令执行操作时,程序就卡在那了,但是其他操...
  • clamaa
  • clamaa
  • 2017年04月11日 09:57
  • 402

eclipse构建maven scala 项目 编译成功

eclipse构建maven+scala+spark工程 eclipse构建maven scala 项目 编译成功
  • ldds_520
  • ldds_520
  • 2016年07月05日 13:28
  • 7782

JAVA调用系统命令或可执行程序

JAVA调用系统命令或可执行程序
  • educast
  • educast
  • 2016年05月26日 15:16
  • 3306
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java执行外部程序(Apache Commons Exec)
举报原因:
原因补充:

(最多只允许输入30个字)