文档章节

自动运行任务

罪恶的花生
 罪恶的花生
发布于 2016/04/12 23:07
字数 1917
阅读 152
收藏 22
点赞 1
评论 0

如何写一个自动运行定时任务程序,我知道有很多人喜欢quartz,我也喜欢,但是我喜欢简单。


当有一个需求时,第一件事就是找方法,比如,我现在需要做一个定时程序,定时触发,定时执行。

因为我的需求很简单,所以我决定使用Timer和TimerTask就可以解决我的需求,于是,我先创建了一个Web项目,

然后,当程序启动时,运行程序自动启动,第一想到的是servlet,

开始撸代码了,

第一个创建HttpServletSysLoad

加入两个仓库,用来存放Timer和TimerTask

public static List<TaskJob> tasks = new ArrayList<TaskJob>();

private static List<Timer> timers = new ArrayList<Timer>();

当然你也可以吧初始化放到:

public SysLoad() {

            tasks = new ArrayList<TaskJob>();

            timers = new ArrayList<Timer>();

    logger.info("建立系统启动自动服务");

}

第二部,在初始化HttpServlet时,自动初始化所有定时任务,

这时候,你需要考虑,是在这里写死方法,还是程序动态生成。

像我这样懒得人,一般都会使用程序动态生成,

找了一个ClassUtil类,通过查找指定包下面所有类的方法来初始化。然后就有了下面的代码。

public void init() throws ServletException {

logger.info("系统启动自动服务");

String startTask = getInitParameter("startTask");

// 启动定时器

if (startTask.equals("true")) {

logger.info("系统开启自动运行服务");

List<Class<?>> jobclasses = ClassUtil.getClasses("cn.wangkai.task.job");

logger.info("获取"+jobclasses.size()+"任务!");

for (Class<?> jobclass : jobclasses) {

try {

TaskJob task = (TaskJob) jobclass.newInstance();

task.getRunTime();

Timer timer = new Timer();

timer.schedule( (TimerTask) task,1000*task.getRunTime(), 1000*task.getRunTime());

tasks.add(task);

timers.add(timer);

logger.info(task.getTaskname()+"开始工作,间隔"+task.getRunTime()+"秒!");

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

}


初始化完毕后,还需要讲初始化的数据在关闭时后reload时销毁,增加如下代码

public void destroy() {

logger.info("正在关闭自动服务");

try{

for (TaskJob task : tasks) {

if(task!=null)tasks.remove(task);

}

}catch(Exception e){

}

try{

for (Timer timer : timers) {

if (timer != null) {

timer.cancel();

}

timers.remove(timer);

}

}catch(Exception e){

}

logger.info("================tasks="+tasks.size()+"=====================");

logger.info("================timers="+timers.size()+"=====================");

super.destroy();

}

第三步加入web.xml

  <servlet>

<servlet-name>SysLoad</servlet-name>

<servlet-class>cn.wangkai.task.taskjob.SysLoad</servlet-class>

<init-param>

<param-name>startTask</param-name>

<param-value>true</param-value>

</init-param>

<init-param>

<param-name>intervalTime</param-name>

<param-value>1</param-value>

</init-param>

<load-on-startup>20</load-on-startup>

</servlet>

剩下就是如何实现TaskJob

第一步创建一个接口,


public interface TaskJob  {

/**

* 获取服务运行描述信息

* @return

*/

public String getMessage();

/**

* 设置服务运行描述信息

* @param message

*/

public void setMessage(String message);

/**

* 得到任务名称

* @return

*/

public String getTaskname() ;

/**

* 设置当前任务名称

* @param taskname

*/

public void setTaskname(String taskname);

/**

* 获取当前任务运行时间

* @return

*/

public int getRunTime() ;

/**

* 设置当前任务运行时间

* @param runTime

*/

public void setRunTime(int runTime);

/**

* 任务是否暂停

* @return

*/

public boolean isRunning() ;

/**

* 设置任务暂停状态

* @param isRunning

*/

public void setRunning(boolean isRunning) ;

}

第二部创建一个实现方法


import java.util.TimerTask;

import java.util.logging.Logger;


import javax.servlet.ServletContext;


import org.apache.commons.lang.math.NumberUtils;


import cn.wangkai.util.ProUtil;

import cn.wangkai.util.StackTraceUtils;



public class TaskJobImp extends TimerTask implements TaskJob {

private static Logger logger = Logger.getAnonymousLogger();

public TaskJobImp(ServletContext context) {

}

//运行描述

private String Message=null;

//程序名称

private String taskname=getClass().getName();

//多长时间,时间秒

private int RunTime=10;

//正常运行

private boolean isRunning = true;

public TaskJobImp() {

}


private ServletContext context;


public void setContext(ServletContext context) {

logger.info(getTaskname()+"任务开始启动!");

this.context = context;

}


public void run() {

if (isRunning()) {

Message = getTaskname()+"上次启动时间\n\t";

try {

Message = Message+"程序运行中....\n\t";

//TODO

Message = Message+"任务启动完成 。\n\t";

} catch (Exception e) {

Message = Message+"出现错误:"+StackTraceUtils.getStackTrace(e);

}finally{

}

logger.info(Message);

}

}


public ServletContext getContext() {

return context;

}


public String getMessage() {

return Message;

}


public void setMessage(String message) {

Message = message;

}


public String getTaskname() {

return taskname;

}


public void setTaskname(String taskname) {

this.taskname = taskname;

}


public int getRunTime() {

RunTime = NumberUtils.toInt(ProUtil.read(getClass().getName()+"_runtime",RunTime+"",true),RunTime);

return RunTime;

}


public void setRunTime(int runTime) {

RunTime = runTime;

}


public boolean isRunning() {

return isRunning;

}


public void setRunning(boolean isRunning) {

this.isRunning = isRunning;

}


    public boolean cancel() {

    logger.info(getTaskname()+"正在退出!");

    return super.cancel();

    }


第四步,我们在cn.wangkai.task.job包中创建一个测试类吧

package cn.wangkai.task.job;



import java.util.logging.Logger;


import cn.wangkai.task.taskjob.TaskJobImp;

import cn.wangkai.util.StackTraceUtils;



public class SampleTask extends TaskJobImp{

private String Message=null;

private static Logger logger = Logger.getAnonymousLogger();

public void run() {

if (isRunning()) {

Message = "\r\n"+getTaskname()+"上次启动时间\r\n";

try {

Message = Message+"程序运行中....\r\n";

//TODO 这里就是你需要实现的代码。

Message = Message+"任务启动完成 。";

} catch (Exception e) {

Message = Message+"出现错误:"+StackTraceUtils.getStackTrace(e);

}finally{

}

logger.info(Message);

}

}

}


好了,代码撸完了,可以睡觉了,

其他工具方法

ClassUtil.java(网上找的,我也懒得写)


public static void main(String[] args) throws Exception {

List<Class<?>> classes = ClassUtil.getClasses("cn.wangkai.task.job");

for (Class<?> clas : classes) {

System.out.println(clas.getName());

}

}


/**

* 取得某个接口下所有实现这个接口的类

*/

public static List<Class<?>> getAllClassByInterface(Class<?> c) {

List<Class<?>> returnClassList = null;


if (c.isInterface()) {

// 获取当前的包名

String packageName = c.getPackage().getName();

// 获取当前包下以及子包下所以的类

List<Class<?>> allClass = getClasses(packageName);

if (allClass != null) {

returnClassList = new ArrayList<Class<?>>();

for (Class<?> classes : allClass) {

// 判断是否是同一个接口

if (c.isAssignableFrom(classes)) {

// 本身不加入进去

if (!c.equals(classes)) {

returnClassList.add(classes);

}

}

}

}

}


return returnClassList;

}


/*

* 取得某一类所在包的所有类名 不含迭代

*/

public static String[] getPackageAllClassName(String classLocation, String packageName) {

// 将packageName分解

String[] packagePathSplit = packageName.split("[.]");

String realClassLocation = classLocation;

int packageLength = packagePathSplit.length;

for (int i = 0; i < packageLength; i++) {

realClassLocation = realClassLocation + File.separator + packagePathSplit[i];

}

File packeageDir = new File(realClassLocation);

if (packeageDir.isDirectory()) {

String[] allClassName = packeageDir.list();

return allClassName;

}

return null;

}


/**

* 从包package中获取所有的Class

* @param pack

* @return

*/

public static List<Class<?>> getClasses(String packageName) {


// 第一个class类的集合

List<Class<?>> classes = new ArrayList<Class<?>>();

// 是否循环迭代

boolean recursive = true;

// 获取包的名字 并进行替换

String packageDirName = packageName.replace('.', '/');

// 定义一个枚举的集合 并进行循环来处理这个目录下的things

Enumeration<URL> dirs;

try {

dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

// 循环迭代下去

while (dirs.hasMoreElements()) {

// 获取下一个元素

URL url = dirs.nextElement();

// 得到协议的名称

String protocol = url.getProtocol();

// 如果是以文件的形式保存在服务器上

if ("file".equals(protocol)) {

// 获取包的物理路径

String filePath = URLDecoder.decode(url.getFile(), "UTF-8");

// 以文件的方式扫描整个包下的文件 并添加到集合中

findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);

} else if ("jar".equals(protocol)) {

// 如果是jar包文件

// 定义一个JarFile

JarFile jar;

try {

// 获取jar

jar = ((JarURLConnection) url.openConnection()).getJarFile();

// 从此jar包 得到一个枚举类

Enumeration<JarEntry> entries = jar.entries();

// 同样的进行循环迭代

while (entries.hasMoreElements()) {

// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件

JarEntry entry = entries.nextElement();

String name = entry.getName();

// 如果是以/开头的

if (name.charAt(0) == '/') {

// 获取后面的字符串

name = name.substring(1);

}

// 如果前半部分和定义的包名相同

if (name.startsWith(packageDirName)) {

int idx = name.lastIndexOf('/');

// 如果以"/"结尾 是一个包

if (idx != -1) {

// 获取包名 把"/"替换成"."

packageName = name.substring(0, idx).replace('/', '.');

}

// 如果可以迭代下去 并且是一个包

if ((idx != -1) || recursive) {

// 如果是一个.class文件 而且不是目录

if (name.endsWith(".class") && !entry.isDirectory()) {

// 去掉后面的".class" 获取真正的类名

String className = name.substring(packageName.length() + 1, name.length() - 6);

try {

// 添加到classes

classes.add(Class.forName(packageName + '.' + className));

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

} catch (IOException e) {

e.printStackTrace();

}


return classes;

}


/**

* 以文件的形式来获取包下的所有Class

* @param packageName

* @param packagePath

* @param recursive

* @param classes

*/

public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,

List<Class<?>> classes) {

// 获取此包的目录 建立一个File

File dir = new File(packagePath);

// 如果不存在或者 也不是目录就直接返回

if (!dir.exists() || !dir.isDirectory()) {

return;

}

// 如果存在 就获取包下的所有文件 包括目录

File[] dirfiles = dir.listFiles(new FileFilter() {

// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)

public boolean accept(File file) {

return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));

}

});

// 循环所有文件

for (File file : dirfiles) {

// 如果是目录 则继续扫描

if (file.isDirectory()) {

findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,

classes);

} else {

// 如果是java类文件 去掉后面的.class 只留下类名

String className = file.getName().substring(0, file.getName().length() - 6);

try {

// 添加到集合中去

classes.add(Class.forName(packageName + '.' + className));

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

}


ProUtil.java 本人原创

详见:http://www.oschina.net/code/snippet_54124_55380


StackTraceUtils.java 很久以前写的,一直在用


import java.io.PrintWriter;

import java.io.StringWriter;

import java.io.Writer;

public class StackTraceUtils {

    /**

     * 将异常堆栈转换为字符串

     * @param aThrowable 异常

     * @return String

     */

    public static String getStackTrace(Throwable aThrowable) {

        final Writer result = new StringWriter();

        final PrintWriter printWriter = new PrintWriter(result);

        aThrowable.printStackTrace(printWriter);

        return result.toString();

      }

}







© 著作权归作者所有

共有 人打赏支持
罪恶的花生

罪恶的花生

粉丝 70
博文 46
码字总数 36703
作品 0
杭州
部门经理
定时任务-quartz的使用,实现可页面化管理

定时任务-quartz的使用,实现可页面化管理 使用spring+quartz实现定时任务的页面化管理。主要特点: 1.时间表达式等信息配置在数据库中,从而实现页面化管理。 2.可以手动执行或者停止单个任...

chaun
2015/07/30
0
0
Linux定时任务的使用

Linux下的定时任务,crontab是一个非常有用的命令(大部分的自动完成的工作都需要用到自动执行命令) 这里演示一个非常简单的定时任务设置。(用来做以后所有复杂的自动化工作的前提)。 先写...

熊猫88
2016/01/25
77
0
windows XP 下空闲时自动锁定

xp在登陆后无法在长时间空闲时无法自动锁定机器,可以通过win键+L键实现锁定或者在运行里输入Rundll32.exeUSER32.dll ,LockWorkStation回车然后会锁定机器,但是这样操作起来比较麻烦。 经过...

晨曦之光
2012/03/09
0
0
第四十章:基于SpringBoot & Quartz完成定时任务分布式多节点负载持久化

在上一章【第三十九章:基于SpringBoot & Quartz完成定时任务分布式单节点持久化】中我们已经完成了任务的持久化,当我们创建一个任务时任务会被定时任务框架自动持久化到数据库,我们采用的...

恒宇少年
2017/11/12
0
0
定时任务调度系统--opencron

opencron:一个功能完善且通用的开源定时任务调度系统,拥有先进可靠的自动化任务管理调度功能,提供可操作的web图形化管理满足多种场景下各种复杂的定时任务调度,同时集成了linux实时监控,we...

benjobs
2017/04/18
12.4K
9
易客CRM控制面板

易客CRM运行环境专用控制面板介绍 易客CRM(http://www.c3crm.com)控制面板是采用快手和AAuto编程语言开发,针对xampp运行环境开发的控制面板,功能介绍如下: 1、服务启动apache和mysql,自动...

dfar2008
2013/06/27
2.4K
0
benjobs/OpenCron

opencron 一个功能完善真正通用的linux定时任务调度定系统,满足多种场景下各种复杂的定时任务调度,同时集成了linux实时监控,webssh,提供一个方便管理定时任务的平台. 你是否有定时执行任务计...

benjobs
2016/11/12
0
0
Apache Storm工作流程

一个工作的Storm集群应该有一个Nimbus和一个或多个supervisors。另一个重要的节点是Apache ZooKeeper,它将用于nimbus和supervisors之间的协调。 现在让我们仔细看看Apache Storm的工作流程 ...

h8b6pk7m7r8
2017/12/06
0
0
wuauclt.exe是什么进程?为什么运行?wuauclt.exe进程介绍

摘自:http://mtoou.info/wuauclt-exe/ Windows系统用户可以通过任务管理器到wuauclt.exe进程是否运行,如下图所示: 那么wuauclt.exe是什么进程及它为什么会运行呢?,本文或许对你有所帮助...

mtoou
2012/12/14
0
0
iOS多线程 Swift4 GCD深入解析

iOS多线程深入解析 必要的概念 进程/线程 进程:进程指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个能独立运行的活动实体。 线程:线程是进...

一蓑烟羽
2017/11/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

nodejs安装以及环境配置(很好的node安装和配置文章,少走很多弯路)

一、安装环境 1、本机系统:Windows 10 Pro(64位) 2、Node.js:v6.9.2LTS(64位) 二、安装Node.js步骤 1、下载对应你系统的Node.js版本:https://nodejs.org/en/download/ 2、选安装目录进...

sprouting
15分钟前
0
0
Redisson

了解了Redisson,发现使用挺简单的,接下来准备深入学习一下。 Redisson介绍 Redisson是架设于Redis基础之上的一个Java驻内存数据网格(In-Memory Data Grid) Redisson在基于NIO的Netty框架上...

to_ln
16分钟前
0
0
python有哪些好玩的应用实现,用python爬虫做一个二维码生成器

python爬虫不止可以批量下载数据,还可以有很多有趣的应用,之前也发过很多,比如天气预报实时查询、cmd版的实时翻译、快速浏览论坛热门帖等等,这些都可以算是爬虫的另一个应用方向! 今天给...

python玩家
16分钟前
0
0
jq 判断复选框是否被选中,复选框后台接收

1. 效果 2. 代码 html部分: JS部分: var rememberLogin = $("#rememberLoginId").is(':checked')//获取复选框是否被选中 var rememberLoginval = $("#rememberLoginId").attr('value')//拿......

Lucky_Me
23分钟前
0
0
python爬虫日志(3)-爬去异步加载网页

在浏览器检查元素页面中,选取Network中的XHR选项即可观察每次加载页面,网页发出的请求,观察url的规律即可利用封装的函数对每一页进行爬取。

茫羽行
23分钟前
0
0
《趣谈网络协议》之为什么要学习网络协议?

一、协议 1.协议的定义 简单说协议就是一个规则,保证沟通交流双方可以互相听懂、理解或者可以双方合作可以顺利进行的一个约定和规则。 2.生活中例子 (1)有一种叫“程序猿”的物种,敲着一种...

aibinxiao
25分钟前
1
0
Python数据分析numpy基础-维度的认识

什么是多维数组? 核心对象是同型的多维数组(简单理解就是一个表格,通常内容都是些数字),具有相同的数据类型。 概念: 1. axes(轴):数组的维度统称为轴。 2. rank:轴的数量称为rank。...

十年磨一剑3344
29分钟前
0
0
Java 正则表达式相关资料

1.java正则表达式过滤html标签

IT追寻者
32分钟前
0
0
点赞出现数字变大效果

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .container{ padding: 50px; border: 1px solid #dddddd; } .item{ position: relative; } ......

南桥北木
51分钟前
0
0
anroid中批量将px转换成dp

package com.qu;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class Aaaa {public static void main(String[] args) {String fi......

android-key
52分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部