Spring Batch 中XML調用CMD的方法

在SpringBatch中調用cmd,有以下兩種常用方法

Spring Batch 中XML調用CMD的方法

1.新定義一個Tasklet類,在裡面用調用cmd。

cmd /c dir 是執行完dir命令後關閉命令窗口。

cmd /k dir 是執行完dir命令後不關閉命令窗口。

cmd /c start dir 會打開一個新窗口後執行dir指令,原窗口會關閉。

cmd /k start dir 會打開一個新窗口後執行dir指令,原窗口不會關閉。

可以用cmd /?查看幫助信息。

<code>demoTasklet.java

Runtime rt = Runtime.getRuntime();
Process p = rt.exec("cmd.exe /c start demo.bat");
System.out.println(p.toString());/<code>

2.通過SpringBatch所提供的自帶的Tasklet來調用cmd。

<code>demoJob.xml




<step>
<tasklet>
/<step>

<bean>
<property>
<property>
<property>

/<bean>/<code>

通過調用SpringBatch框架封裝好的SystemCommandTasklet類來調用cmd,上面四個參數中,“command”,“workingDirectory”,"timeout"為必填參數。

下面附上SystemCommandTasklet的源代碼,可以看出,通過該方法來執行cmd,實際上也是應用

Runtime.getRuntime().exec(command, environmentParams, workingDirectory);

來進行實現的。所以,具體用哪種方法去調用cmd比較方便,就是仁者見仁智者見智了。

<code>/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.batch.core.step.tasklet;

import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.core.scope.context.ChunkContext;

import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.util.Assert;

/**
* {@link Tasklet} that executes a system command.
*
* The system command is executed asynchronously using injected
* {@link #setTaskExecutor(TaskExecutor)} - timeout value is required to be set,
* so that the batch job does not hang forever if the external process hangs.
*
* Tasklet periodically checks for termination status (i.e.
* {@link #setCommand(String)} finished its execution or
* {@link #setTimeout(long)} expired or job was interrupted). The check interval
* is given by {@link #setTerminationCheckInterval(long)}.
*
* When job interrupt is detected tasklet's execution is terminated immediately
* by throwing {@link JobInterruptedException}.
*
* {@link #setInterruptOnCancel(boolean)} specifies whether the tasklet should
* attempt to interrupt the thread that executes the system command if it is
* still running when tasklet exits (abnormally).
*
* @author Robert Kasanicky
*/
public class SystemCommandTasklet extends StepExecutionListenerSupport implements Tasklet, InitializingBean {

\tprotected static final Log logger = LogFactory.getLog(SystemCommandTasklet.class);

\tprivate String command;

\tprivate String[] environmentParams = null;

\tprivate File workingDirectory = null;

\tprivate SystemProcessExitCodeMapper systemProcessExitCodeMapper = new SimpleSystemProcessExitCodeMapper();

\tprivate long timeout = 0;

\tprivate long checkInterval = 1000;

\tprivate StepExecution execution = null;

\tprivate TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();

\tprivate boolean interruptOnCancel = false;

\t/**

\t * Execute system command and map its exit code to {@link ExitStatus} using
\t * {@link SystemProcessExitCodeMapper}.
\t */
\tpublic RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

\t\tFutureTask<integer> systemCommandTask = new FutureTask<integer>(new Callable<integer>() {

\t\t\tpublic Integer call() throws Exception {
\t\t\t\tProcess process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
\t\t\t\treturn process.waitFor();
\t\t\t}

\t\t});

\t\tlong t0 = System.currentTimeMillis();

\t\ttaskExecutor.execute(systemCommandTask);

\t\twhile (true) {
\t\t\tThread.sleep(checkInterval);
\t\t\tif (systemCommandTask.isDone()) {
\t\t\t\tcontribution.setExitStatus(systemProcessExitCodeMapper.getExitStatus(systemCommandTask.get()));
\t\t\t\treturn RepeatStatus.FINISHED;
\t\t\t}
\t\t\telse if (System.currentTimeMillis() - t0 > timeout) {
\t\t\t\tsystemCommandTask.cancel(interruptOnCancel);
\t\t\t\tthrow new SystemCommandException("Execution of system command did not finish within the timeout");
\t\t\t}
\t\t\telse if (execution.isTerminateOnly()) {
\t\t\t\tsystemCommandTask.cancel(interruptOnCancel);
\t\t\t\tthrow new JobInterruptedException("Job interrupted while executing system command '" + command + "'");
\t\t\t}
\t\t}

\t}

\t/**
\t * @param command command to be executed in a separate system process
\t */
\tpublic void setCommand(String command) {
\t\tthis.command = command;
\t}

\t/**
\t * @param envp environment parameter values, inherited from parent process
\t * when not set (or set to null).
\t */
\tpublic void setEnvironmentParams(String[] envp) {
\t\tthis.environmentParams = envp;
\t}


\t/**
\t * @param dir working directory of the spawned process, inherited from
\t * parent process when not set (or set to null).
\t */
\tpublic void setWorkingDirectory(String dir) {
\t\tif (dir == null) {
\t\t\tthis.workingDirectory = null;
\t\t\treturn;
\t\t}
\t\tthis.workingDirectory = new File(dir);
\t\tAssert.isTrue(workingDirectory.exists(), "working directory must exist");
\t\tAssert.isTrue(workingDirectory.isDirectory(), "working directory value must be a directory");

\t}

\tpublic void afterPropertiesSet() throws Exception {
\t\tAssert.hasLength(command, "'command' property value is required");
\t\tAssert.notNull(systemProcessExitCodeMapper, "SystemProcessExitCodeMapper must be set");
\t\tAssert.isTrue(timeout > 0, "timeout value must be greater than zero");
\t\tAssert.notNull(taskExecutor, "taskExecutor is required");
\t}

\t/**
\t * @param systemProcessExitCodeMapper maps system process return value to
\t * <code>ExitStatus/<code> returned by Tasklet.
\t * {@link SimpleSystemProcessExitCodeMapper} is used by default.
\t */
\tpublic void setSystemProcessExitCodeMapper(SystemProcessExitCodeMapper systemProcessExitCodeMapper) {
\t\tthis.systemProcessExitCodeMapper = systemProcessExitCodeMapper;
\t}

\t/**
\t * Timeout in milliseconds.
\t * @param timeout upper limit for how long the execution of the external
\t * program is allowed to last.
\t */
\tpublic void setTimeout(long timeout) {
\t\tthis.timeout = timeout;
\t}

\t/**
\t * The time interval how often the tasklet will check for termination
\t * status.
\t *
\t * @param checkInterval time interval in milliseconds (1 second by default).
\t */
\tpublic void setTerminationCheckInterval(long checkInterval) {
\t\tthis.checkInterval = checkInterval;
\t}


\t/**
\t * Get a reference to {@link StepExecution} for interrupt checks during
\t * system command execution.
\t */
\t@Override
\tpublic void beforeStep(StepExecution stepExecution) {
\t\tthis.execution = stepExecution;
\t}

\t/**
\t * Sets the task executor that will be used to execute the system command
\t * NB! Avoid using a synchronous task executor
\t */
\tpublic void setTaskExecutor(TaskExecutor taskExecutor) {
\t\tthis.taskExecutor = taskExecutor;
\t}

\t/**
\t * If <code>true/<code> tasklet will attempt to interrupt the thread
\t * executing the system command if {@link #setTimeout(long)} has been
\t * exceeded or user interrupts the job. <code>false/<code> by default
\t */
\tpublic void setInterruptOnCancel(boolean interruptOnCancel) {
\t\tthis.interruptOnCancel = interruptOnCancel;
\t}

}

/<integer>/<integer>/<integer>/<code>


分享到:


相關文章: