简单实用后台任务执行框架(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
- 简单实用后台任务执行框架(Struts2+Spring+AJAX前端web界面可以获取进度)
- 前端页面动态获取后台执行sql的执行条数(超实用)
- ssh框架ajax获取后台list数据简单例子
- Ajax 后台正确执行 但在前台获取不到返回值 但打断点就可以
- Spring定时任务的简单例子----非常实用----不需要做什么改动就可以使用哦
- Jquery progressbar通过Ajax请求获取后台进度演示
- java后台设计简单的json数据接口,设置可跨域访问,前端ajax获取json数据
- android AsyncTask 可以更新界面的后台任务
- 前端展示后台处理进度
- ajax获取后台数据+spring MVC
- 开发框架之spring执行定时任务
- Spring框架下的定时任务执行
- ajax 获取进度
- Web框架和前端框架以及Ajax的常用框架易混淆(混为一谈)
- Web app 前端框架ratchet使用push.js界面跳转后,js代码无法执行的解决方法
- Web前端框架 界面UI框架调查说明
- Struts2框架简单的AJAX应用
- 前端ajax获取从后台传回的数据
- 内建函数-frozenset
- Codeforces 433A Kitahara Haruki's Gift
- Linux 下编译并安装配置 Qt 全过程
- java异常处理机制示例(java抛出异常、捕获、断言)
- (*(volatile unsigned long *)) 的理解(
- 简单实用后台任务执行框架(Struts2+Spring+AJAX前端web界面可以获取进度)
- Codeforces 433B Kuriyama Mirai's Stones
- 形参和实参的区别与联系简要分析
- Java
- 学习
- jquery 获取input的checked属性问题
- 编辑文章 - 博客频道 - CSDN.NET
- TCP1
- 【LeetCode】Subsets II