简单实用后台任务执行框架(Struts2+Spring+AJAX前端web界面可以获取进度)

来源:互联网 发布:js log函数 编辑:程序博客网 时间:2024/05/19 03:20

使用场景:

在平常web开发过程中,有时操作员要做一个后台会运行很长时间的任务(如上传一个大文件到后台处理),而此时前台页面仍需要给用户及时的进度信息反馈,同时还要避免前台页面超时。

框架介绍:

本架构采用Struts+Spring+AJAX(jquery)方式实现,前台提交任务到后台,然后通过AJAX方式周期性获取任务进度,展示给用户看。

本框架支持提交任务、查看任务进展、停止任务、删除任务。

使用java线程池的技术来执行任务,避免不停的生成新的线程;

代码下载(内含使用样例):

https://github.com/jerrymousecn/daemo_tasks

下载包说明:

1)demo/daemonTasks.war为tomcat发布包(zip格式),可以直接放到tomcat的webapps目录;

2)demo/demo_source目录是eclipse样例项目代码

3)source目录是本框架源代码


主要代码:

1.DaemonTask.java

后台任务基础类

package cn.jerry.tools.tasks;import java.util.Date;public abstract class DaemonTask implements Runnable {private String taskID;private String taskName;private String taskDesc;private boolean isStartedFlag = false;;private boolean isTerminated = false;;private int progress;private Date startTime;private Date terminatedTime;protected boolean toStopFlag = false;protected abstract void execute();protected void setProgress(int progress) {this.progress = progress;}public void run() {this.isStartedFlag = true;this.execute();this.isTerminated = true;this.terminatedTime = new Date();}public String getTaskID() {return taskID;}public void setTaskID(String taskID) {this.taskID = taskID;}public boolean isStarted() {return isStartedFlag;}public boolean getIsTerminated() {return isTerminated;}public void setToStopFlag(boolean toStopFlag) {this.toStopFlag = toStopFlag;}public Date getStartTime() {return startTime;}public Date getTerminatedTime() {return terminatedTime;}public int getProgress() {return progress;}public String getTaskName() {return taskName;}public void setTaskName(String taskName) {this.taskName = taskName;}public String getTaskDesc() {return taskDesc;}public void setTaskDesc(String taskDesc) {this.taskDesc = taskDesc;}}

2.TaskManager.java

后台任务管理类,支持添加任务,停止任务,删除任务,查看任务,对已完成任务进行定期清理,获取任务进度

package cn.jerry.tools.tasks;import java.util.Collections;import java.util.Date;import java.util.Map;import java.util.Timer;import java.util.TimerTask;import java.util.UUID;import java.util.Map.Entry;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TaskManager {private static TaskManager taskManager = new TaskManager();private ExecutorService executorService = Executors.newCachedThreadPool();private ConcurrentMap<String, DaemonTask> taskMap = new ConcurrentHashMap<String, DaemonTask>();private final int TASK_NOT_FOUND = -1;private TaskCleaner taskCleaner = new TaskCleaner(taskMap);private Timer timer = new Timer();private final int CLEAN_PERIOD = 200000;  //in millisecondsprivate String getUniqueID() {return UUID.randomUUID().toString();}private TaskManager() {startTerminatedTaskCleanTimer();}private void startTerminatedTaskCleanTimer() {timer.schedule(taskCleaner, 0, CLEAN_PERIOD);}private void stopTerminatedTaskCleanTimer() {timer.cancel();}public static TaskManager getInstance() {return taskManager;}public synchronized String addTaskAndStart(DaemonTask task) {String taskID = getUniqueID();task.setTaskID(taskID);taskMap.put(taskID, task);executorService.execute(task);return taskID;}public synchronized void stopTask(String taskID) {DaemonTask task = getTask(taskID);if (task != null) {task.setToStopFlag(true);}}public synchronized void delFinishedTask(String taskID) {DaemonTask task = getTask(taskID);if (task != null) {if (task.getIsTerminated()) {taskMap.remove(taskID);}}}public DaemonTask getTask(String taskID) {return taskMap.get(taskID);}public Map<String, DaemonTask> getTasksForView() {Map<String, DaemonTask> map = Collections.unmodifiableMap(taskMap);return map;}public int getProgress(String taskID) {int progress = TASK_NOT_FOUND;DaemonTask task = getTask(taskID);if (task != null) {progress = task.getProgress();}return progress;}}class TaskCleaner extends TimerTask {private ConcurrentMap<String, DaemonTask> taskMap;public TaskCleaner(ConcurrentMap<String, DaemonTask> taskMap) {this.taskMap = taskMap;}@Overridepublic void run() {for (Entry<String, DaemonTask> entry : taskMap.entrySet()) {String taskID = entry.getKey();DaemonTask task = entry.getValue();if (task.getIsTerminated()) {Date terminatedTime = task.getTerminatedTime();Date now = new Date();long timeOffset = getTimeOffset(terminatedTime, now);if (timeOffset > 10000) {taskMap.remove(taskID);System.out.println("task: " + taskID + " is removed");}}}}private long getTimeOffset(Date date1, Date date2) {long time1 = date1.getTime();long time2 = date2.getTime();long offset = time2 - time1;if (offset < 0) {offset = -offset;}return offset;}}

3.任务样例TestTask.java

关键点需要注意: 方法中需要自行计算进度(完成时,进度应设置为100),并且要对toStopFlag进行判断,用于终止任务。

package cn.jerry.tools.tasks;public class TestTask extends DaemonTask {@Overrideprotected void execute() {for (int i = 0; i < 10; i++) {if(this.toStopFlag==false){int progress = (i + 1) * 100 / 10;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.setProgress(progress);}}}}

4.前台查询状态页面getTaskResult.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %><html><head><script type="text/javascript" src="js/jquery-1.11.1.min.js"></script><link rel="stylesheet" href="css/jquery-ui.css"><script src="js/jquery-ui.js"></script><link rel="stylesheet" href="css/style.css"><script type="text/javascript">var intervalId; function trim(str){return str.replace(/(^\s*)|(\s*$)/g, ""); } function getprogress() {htmlobj=$.ajax({url:"getTaskProgress.jsp?taskid="+'<s:property value="taskid"/>',cache:false,async:false});str = trim(htmlobj.responseText);$("#myDiv").html(str);$( "#progressbar" ).progressbar({      value: parseInt(str)});if(parseInt(str)>=100){clearInterval(intervalId);}}$(document).ready(function(){intervalId = setInterval(getprogress, 1000);});</script></head><body>Task [<s:property value="taskName"/>]progress:<div id="progressbar"></div><div id="myDiv"></div></body></html>

5.相关截图

1)进度页面截图:

2)查看任务列表




声明:

本框架中使用的进度条代码实现来自以下网站,版权不属于本人,本框架仅用于学习交流。

http://jqueryui.com/progressbar/#animated


转载请注明出处:http://blog.csdn.net/u014569459/article/details/26873097



1 0
原创粉丝点击