一。 直接编写相关代码。
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(); } }
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()); } }
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(); } }
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(); } }