一。 直接编写相关代码。
main.java
package com.ffcs.icity.app.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main implements Runnable {
private final static Logger logger = LoggerFactory.getLogger(Main.class);
private ApplicationContext context;
private void init() {
logger.info("initializing Spring IoC container");
this.context = new ClassPathXmlApplicationContext(new String[] { "classpath*:conf/applicationContext-*.xml","classpath*:/applicationContext-*.xml" });
logger.info("initialized Spring IoC container");
}
private void processOnceTask(){
OnceTaskExecutor onceTaskExecutor=(OnceTaskExecutor)this.context.getBean(OnceTaskExecutor.class);
if(onceTaskExecutor!=null){
logger.info("executing OnceTasks");
onceTaskExecutor.execute();
logger.info("executed OnceTasks");
}
}
private void processScheduledTask(){
ScheduledTaskExecutor scheduledTaskExecutor=(ScheduledTaskExecutor)this.context.getBean(ScheduledTaskExecutor.class);
if (scheduledTaskExecutor!=null) {
logger.info("executing ScheduledTasks");
scheduledTaskExecutor.execute();
logger.info("executing ScheduledTasks");
}
}
@Override
public void run() {
init();
processScheduledTask();
processOnceTask();
}
}
OnceTask.java
package com.ffcs.icity.app.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 执行一次的任务.
* @author linwei
*
*/
public abstract class OnceTask implements Runnable {
protected Logger logger;
public OnceTask() {
this.logger = LoggerFactory.getLogger(this.getClass());
}
protected abstract void doTask();
@Override
public void run() {
try {
this.logger.info("starting task");
doTask();
this.logger.info("completed task");
} catch (Throwable throwable) {
this.logger.error("failed task", throwable);
}
}
}
package com.ffcs.icity.app.core;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* 单次任务调度执行器
* @author linwei
*
*/
public class OnceTaskExecutor implements ApplicationContextAware {
private final static Logger logger = LoggerFactory.getLogger(OnceTaskExecutor.class);
private List<OnceTask> onceTasks;
public void execute() {
logger.info("OnceTask count:{}", this.onceTasks.size());
for (OnceTask onceTask : this.onceTasks) {
logger.info("executing {}", onceTask);
new Thread(onceTask).start();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取配置文件中BEAN类型是OnceTask的相关BEAN信息
this.onceTasks = new ArrayList<OnceTask>(applicationContext.getBeansOfType(OnceTask.class).values());
}
}
ScheduledTask.java
package com.ffcs.icity.app.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
* 定时任务
* @author linwei
*
*/
public abstract class ScheduledTask implements Runnable {
private final static String LOG_MDC_TASK_SID = "SID";
protected Logger logger;
/**
* 执行次数.
*/
private long count = 1;
/**
* 错误次数.
*/
private long errCount = 0;
public ScheduledTask() {
this.logger = LoggerFactory.getLogger(this.getClass());
}
public abstract void doTask();
@Override
public void run() {
MDC.put(LOG_MDC_TASK_SID, Long.toString(count));
try {
logger.info("starting task[{}]", count);
long startTime = System.currentTimeMillis();
doTask();
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("completed task[{}],elapsed time: {} ms", count, elapsedTime);
} catch (Throwable throwable) {
errCount++;
logger.error("failed task[" + count + "],error total: " + errCount, throwable);
} finally {
MDC.remove(LOG_MDC_TASK_SID);
count++;
}
}
/**
* 子类覆盖此方法,提供表示执行时间定义的Cron表达式.同时指示此定时任务的执行方式为基于cron表达式.
*/
public String getCron() {
return null;
}
/**
* 子类覆盖此方法,用于设置两次任务执行的间隔时间(单位:毫秒).同时指示此定时任务的执行方式为以固定间隔时间的重复执行(
* 下一次的执行会在上一次执行完成后固定的时间间隔后开始).
*
* 注:如果子类同时覆盖了getCron()方法,那么优先使用基于cron表达式方式的定时任务.
*
*/
public long getDelay() {
return -1;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ScheduledTask [cron=");
builder.append(this.getCron());
builder.append(", delay=");
builder.append(this.getDelay());
builder.append("]");
return builder.toString();
}
}
ScheduledTaskExecutor.java
package com.ffcs.icity.app.core;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
/**
* 定时任务执行器
* @author linwei
*
*/
public class ScheduledTaskExecutor implements ApplicationContextAware{
private final static Logger logger = LoggerFactory.getLogger(ScheduledTaskExecutor.class);
private List<ScheduledTask> scheduledTasks;
private TaskScheduler taskScheduler;
public void execute() {
logger.info("ScheduledTask count:{}", this.scheduledTasks.size());
for (ScheduledTask scheduledTask : this.scheduledTasks) {
if(scheduledTask.getCron()!=null){
logger.info("executing {} by cron", scheduledTask);
this.taskScheduler.schedule(scheduledTask,new CronTrigger(scheduledTask.getCron()));
}else if(scheduledTask.getDelay()>=0){
logger.info("executing {} by delay", scheduledTask);
this.taskScheduler.scheduleWithFixedDelay(scheduledTask, scheduledTask.getDelay());
}else{
logger.warn("invalid {}. because subclass must override getCron() or getDelay().", scheduledTask);
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.scheduledTasks = new ArrayList<ScheduledTask>(applicationContext.getBeansOfType(ScheduledTask.class).values());
}
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
}
二。 编写相关配置文件信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
default-lazy-init="false">
<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com.ffcs.icity" />
<task:annotation-driven scheduler="scheduler" />
<task:scheduler id="scheduler" pool-size="50" />
<bean id="onceTaskExecutor" class="com.ffcs.icity.app.core.OnceTaskExecutor" />
<bean id="scheduledTaskExecutor" class="com.ffcs.icity.app.core.ScheduledTaskExecutor">
<property name="taskScheduler" ref="scheduler"/>
</bean>
<!-- local development环境 -->
<beans profile="development">
<context:property-placeholder
ignore-resource-not-found="true"
location="classpath*:/application.properties,
classpath*:/application.development.properties" />
</beans>
<!-- test 环境 -->
<beans profile="test">
<context:property-placeholder
ignore-resource-not-found="true"
location="classpath*:/application.properties,
classpath*:/application.test.properties" />
</beans>
<!-- production环境 -->
<beans profile="production">
<context:property-placeholder
ignore-unresolvable="true" location="classpath*:/application.properties" />
</beans>
</beans>
三。 使用实例
在com.ffcs.icity扫描路径下创建相关需要执行的JAVA文件,如下:
TestTask.java
package com.ffcs.icity.test;
import org.springframework.stereotype.Service;
import com.ffcs.icity.app.core.OnceTask;
@Service
public class TestTask extends OnceTask{
@Override
protected void doTask() {
System.err.println("111111");
System.err.println("okok.");
}
}
四。 执行代码。
执行如下方法调用即可。
package test;
import com.ffcs.icity.app.core.Main;
public class Test {
public static void main(String[] args) {
new Main().run();
}
}