Quartz实战
https://my.oschina.net/yinxiaoling/blog/542336?fromerr=s3ko7u33
Quartz实战
>
一、内存型(1)
<bean name="complexJobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.java.job.XXXXXXXXX" />
<property name="durability" value="true" />
</bean>
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="complexJobDetail" />
<!-- 每2分钟执行一次 -->
<property name="cronExpression" value="0 0/2 * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="complexJobDetail" />
</list>
</property>
<propertyname="triggers">
<list>
<refbean="cronTrigger" />
</list>
</property>
</bean>
其中XXXXXXXXX为你的任务类:继承 QuartzJobBean 重写executeInternal方法即可。
二、内存型(2)-防止并发执行
<bean id="XXXXXXX" class="com.java.job.XXXXXXXXXXX" />
<bean name="complexJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="XXXXXXX" />
<property name="targetMethod" value="执行定时任务的方法名" />
<!-- 防止并发执行 -->
<property name="concurrent" value="false" />
</bean>
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="complexJobDetail" />
<!-- 每2分钟执行一次 -->
<property name="cronExpression" value="0 0/2 * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<propertyname="jobDetails">
<list>
<refbean="complexJobDetail" />
</list>
</property>
<propertyname="triggers">
<list>
<refbean="cronTrigger" />
</list>
</property>
</bean>
此方法你实现的的类不需继承、实现任何类、接口。 另外多个job的话则做多个触发器和job然后加到list中间即可。
三、持久化
1、官网下载Quzrtz解压后在目录docs/datables中可以找到需要的建表语句。这里提供mysql-innodb的sql:
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
#
# By: Ron Cordell - roncordell
# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;
2、Spring配置文件:
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<!-- quartz持久化存储 -->
<bean name="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="configLocation" value="classpath:quartz.properties" />
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">CRMscheduler</prop>
<propkey="org.quartz.scheduler.instanceId">AUTO</prop>
<!-- 线程池配置 -->
<propkey="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<propkey="org.quartz.threadPool.threadCount">20</prop>
<propkey="org.quartz.threadPool.threadPriority">5</prop>
<propkey="org.quartz.jobStore.misfireThreshold">120000</prop>
<!-- JobStore 配置 -->
<propkey="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<!-- 集群配置 -->
<propkey="org.quartz.jobStore.isClustered">true</prop>
<propkey="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
<propkey="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>
<!-- 数据表设置 -->
<propkey="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
<propkey="org.quartz.jobStore.dataSource">qzDS</prop>
</props>
</property>
<!--应用启动完后 QuartzScheduler延时10秒再启动 -->
<propertyname="startupDelay"value="10" />
<!-- 注册触发器 -->
<propertyname="triggers">
<list>
<refbean="cronTrigger" />
</list>
</property>
<!-- 注册jobDetail -->
<propertyname="jobDetails">
<list>
<refbean="complexJobDetail" />
</list>
</property>
</bean>
<beanname="complexJobDetail"class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<propertyname="jobClass"value="com.java.job.XXX" />
<propertyname="durability"value="true" />
<propertyname="group"value="jobGroupName_XXX" />
<propertyname="name"value="jobName_XXX" />
</bean>
<beanid="cronTrigger"class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<propertyname="jobDetail"ref="complexJobDetail" />
<!-- 每30分钟执行一次 -->
<propertyname="cronExpression"value="0 0/30 * * * ?" />
<propertyname="name"value="triggerName_XXX" />
<propertyname="group"value="triggerGroupName_XXX" />
</bean>
</beans>
看以看到我们这里自定义了触发器和job的名字、组名还有其他可以自定义的属性,大家可以自定义去试试。
另外一种配置文件形式的方法:
#Main Scheduler Settings
org.quartz.scheduler.instanceName=quartzScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=100
#Configure JDBC-JobStoreTX
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.acquireTriggersWithinLock=true
org.quartz.jobStore.clusterCheckinInterval = 600000
#Configure DataSources
org.quartz.dataSource.myDS.driver=com.alibaba.druid.proxy.DruidDriver
org.quartz.dataSource.myDS.URL=jdbc:mysql://127.0.0.1:3306/数据库名称?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
org.quartz.dataSource.myDS.user=用户名
org.quartz.dataSource.myDS.password=密码
org.quartz.dataSource.myDS.maxConnections=5
org.quartz.dataSource.myDS.validationQuery=select 1 from dual
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
# Configure Plugins
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at\: {4, date, HH\:mm\:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage =Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH\:mm\:ss MM/dd/yyyy}.
上面implements Job 实现execute方法 或者 继承 QuartzJobBean 重写executeInternal方法都可以,也可以换成防止并发的形式。
四、界面管理
Bean
import java.util.Date;
import org.quartz.JobDataMap;
public class JobEntity {
private int jobId;
private String jobType;
private String jobGroup;
private String jobName;
private String triggerName;
private String triggerGroupName;
private String cronExpr;
private Date previousFireTime;
private Date nextFireTime;
private String jobStatus;
private long runTimes;
private long duration;
private Date startTime;
private Date endTime;
private String jobMemo;
private String jobClass;
private String jobMethod;
private String jobObject;
private int count;
private JobDataMap jobDataMap;
public int getJobId() {
return jobId;
}
public void setJobId(int jobId) {
this.jobId = jobId;
}
public String getJobType() {
return jobType;
}
public void setJobType(String jobType) {
this.jobType = jobType;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getTriggerName() {
return triggerName;
}
public void setTriggerName(String triggerName) {
this.triggerName = triggerName;
}
public String getTriggerGroupName() {
return triggerGroupName;
}
public void setTriggerGroupName(String triggerGroupName) {
this.triggerGroupName = triggerGroupName;
}
public String getCronExpr() {
return cronExpr;
}
publicvoidsetCronExpr(String cronExpr) {
this.cronExpr = cronExpr;
}
public Date getPreviousFireTime() {
return previousFireTime;
}
publicvoidsetPreviousFireTime(Date previousFireTime) {
this.previousFireTime = previousFireTime;
}
public Date getNextFireTime() {
return nextFireTime;
}
publicvoidsetNextFireTime(Date nextFireTime) {
this.nextFireTime = nextFireTime;
}
public String getJobStatus() {
return jobStatus;
}
publicvoidsetJobStatus(String jobStatus) {
this.jobStatus = jobStatus;
}
publiclonggetRunTimes() {
return runTimes;
}
publicvoidsetRunTimes(long runTimes) {
this.runTimes = runTimes;
}
publiclonggetDuration() {
return duration;
}
publicvoidsetDuration(long duration) {
this.duration = duration;
}
public Date getStartTime() {
return startTime;
}
publicvoidsetStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
publicvoidsetEndTime(Date endTime) {
this.endTime = endTime;
}
public String getJobMemo() {
return jobMemo;
}
publicvoidsetJobMemo(String jobMemo) {
this.jobMemo = jobMemo;
}
public String getJobClass() {
return jobClass;
}
publicvoidsetJobClass(String jobClass) {
this.jobClass = jobClass;
}
public String getJobMethod() {
return jobMethod;
}
publicvoidsetJobMethod(String jobMethod) {
this.jobMethod = jobMethod;
}
publicintgetCount() {
return count;
}
publicvoidsetCount(int count) {
this.count = count;
}
public String getJobObject() {
return jobObject;
}
publicvoidsetJobObject(String jobObject) {
this.jobObject = jobObject;
}
public JobDataMap getJobDataMap() {
return jobDataMap;
}
publicvoidsetJobDataMap(JobDataMap jobDataMap) {
this.jobDataMap = jobDataMap;
}
}
公共类代码
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzManager {
private static SchedulerFactory ssf = new StdSchedulerFactory();
private static final String JOB_NAME = "DEFAULT_JOB";
private static final String JOB_GROUP_NAME = "DEFAULT_JOBGROUP";
private static final String TRIGGER_NAME = "DEFAULT_TRIGGER";
private static final String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGERGROUP";
/**
* addJob(方法描述:添加定时任务) <br />
* (方法适用条件描述: – 可选)
*
* 使用默认的作业名称: DEFAULT_JOB
* 使用默认的作业组名称: DEFAULT_JOBGROUP
* 使用默认的触发器名称: DEFAULT_TRIGGER
* 使用默认的触发器组名称:DEFAULT_TRIGGERGROUP
*
* @param cls 调用定时任务的class
* @param cron 定时任务的时间通配符
* void
* @exception
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public static void addJob(Class cls, String cron) {
addJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, cls, cron);
}
/**
* addJob(方法描述:添加定时任务) <br />
* (方法适用条件描述: – 可选)
*
* 使用默认的作业组名称: DEFAULT_JOBGROUP
* 使用默认的触发器组名称:DEFAULT_TRIGGERGROUP
*
* @param jobName 作业名称
* @param triggerName触发器名称
* @param cls 调用定时任务的class
* @param cron 定时任务的时间通配符
* void
* @exception
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public static void addJob(String jobName, String triggerName, Class cls, String cron) {
addJob(jobName, JOB_GROUP_NAME, triggerName, TRIGGER_GROUP_NAME, cls, cron);
}
/**
* addJob(方法描述:添加一个定时任务) <br />
* (方法适用条件描述: – 可选)
*
* @param jobName 作业名称
* @param jobGroupName 作业组名称
* @param triggerName 触发器名称
* @param triggerGroupName 触发器组名称
* @param cls 定时任务的class
* @param time 时间表达式
* void
* @exception
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class cls, String cron) {
try {
//获取调度器
Scheduler sched = ssf.getScheduler();
//创建一项作业
JobDetail job = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
//创建一个触发器
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName)
.withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
//告诉调度器使用该触发器来安排作业
sched.scheduleJob(job, trigger);
// 启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* modifyJobTime(方法描述:修改定时任务-先删除在新增) <br />
* (方法适用条件描述: – 可选)
*
* @param jobName 作业名称
* @param jobGroupName 作业组名称
* @param triggerName 触发器名称
* @param triggerGroupName 触发器组名称
* @param cron 时间表达式
* void
* @exception
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public static voidmodifyJobTime(String jobName, String jobGroup, String triggerName, String triggerGroup, String cron) {
try {
Scheduler sched = ssf.getScheduler();
CronTrigger trigger = (CronTrigger) sched.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroup));
if (trigger == null) {
return;
}
String oldCron = trigger.getCronExpression();
if (!oldCron.equalsIgnoreCase(cron)) {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
JobDetail job = sched.getJobDetail(jobKey);
Class jobClass = job.getJobClass();
// 停止触发器
sched.pauseTrigger(triggerKey);
// 移除触发器
sched.unscheduleJob(triggerKey);
// 删除任务
sched.deleteJob(jobKey);
addJob(jobName, jobGroup, triggerName, triggerGroup, jobClass, cron);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* modifyJobTime(方法描述:修改定时任务-只修改触发器和时间重启触发器) <br />
* (方法适用条件描述: – 可选)
*
* @param triggerName 触发器名称
* @param triggerGroupName 触发器组名称
* @param time
* void
* @exception
* @since 1.0.0
*/
publicstaticvoidmodifyJobTime(String triggerName, String triggerGroupName, String time) {
try {
Scheduler sched = ssf.getScheduler();
CronTrigger trigger = (CronTrigger) sched.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronTrigger ct = (CronTrigger) trigger;
// 修改时间
ct.getTriggerBuilder().withSchedule(CronScheduleBuilder.cronSchedule(time)).build();
// 重启触发器
sched.resumeTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* removeJob(方法描述:删除默认组任务) <br />
* (方法适用条件描述: – 可选)
*
* @param jobName 作业名称
* void
* @exception
* @since 1.0.0
*/
publicstaticvoidremoveJob(String jobName) {
try {
Scheduler sched = ssf.getScheduler();
// 停止触发器
sched.pauseTrigger(TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME));
// 移除触发器
sched.unscheduleJob(TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME));
// 删除任务
sched.deleteJob(JobKey.jobKey(jobName, JOB_GROUP_NAME));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* removeJob(方法描述:删除指定组任务) <br />
* (方法适用条件描述: – 可选)
*
* @param jobName 作业名称
* @param jobGroupName 作业组名称
* @param triggerName 触发器名称
* @param triggerGroupName 触发器组名称
* void
* @exception
* @since 1.0.0
*/
publicstaticvoidremoveJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
try {
Scheduler sched = ssf.getScheduler();
// 停止触发器
sched.pauseTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
// 移除触发器
sched.unscheduleJob(TriggerKey.triggerKey(triggerName, triggerGroupName));
// 删除任务
sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* startJobs(方法描述:开始所有定时任务) <br />
* (方法适用条件描述: – 可选)
* void
* @exception
* @since 1.0.0
*/
publicstaticvoidstartJobs() {
try {
Scheduler sched = ssf.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* shutdownJobs(方法描述:停止所有定时任务) <br />
* (方法适用条件描述: – 可选)
* void
* @exception
* @since 1.0.0
*/
publicstaticvoidshutdownJobs() {
try {
Scheduler sched = ssf.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Ctroller代码
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
/**
* 类名称:JobController
* @version
*/
@Controller
@RequestMapping(value = "/job")
public class JobController extends BaseController {
@Resource(name = "quartzScheduler")
private Scheduler quartzScheduler;
@SuppressWarnings("unchecked")
private List<JobEntity> getSchedulerJobInfo() throws SchedulerException {
List<JobEntity> jobInfos = new ArrayList<JobEntity>();
List<String> triggerGroupNames = quartzScheduler.getTriggerGroupNames();
for (String triggerGroupName : triggerGroupNames) {
Set<TriggerKey> triggerKeySet = quartzScheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));
for (TriggerKey triggerKey : triggerKeySet) {
Trigger t = quartzScheduler.getTrigger(triggerKey);
if (t instanceof CronTrigger) {
CronTrigger trigger = (CronTrigger) t;
//CronTrigger trigger = (CronTrigger) quartzScheduler.getTrigger(triggerKey);
JobKey jobKey = trigger.getJobKey();
JobDetail jd = quartzScheduler.getJobDetail(jobKey);
//List<CronTrigger> triggers = (List<CronTrigger>) quartzScheduler.getTriggersOfJob(jobKey);
//CronTrigger cronTrigger = triggers.get(0);
JobEntity jobInfo = new JobEntity();
jobInfo.setJobName(jobKey.getName());
jobInfo.setJobGroup(jobKey.getGroup());
jobInfo.setTriggerName(triggerKey.getName());
jobInfo.setTriggerGroupName(triggerKey.getGroup());
jobInfo.setCronExpr(trigger.getCronExpression());
jobInfo.setNextFireTime(trigger.getNextFireTime());
jobInfo.setPreviousFireTime(trigger.getPreviousFireTime());
jobInfo.setStartTime(trigger.getStartTime());
jobInfo.setEndTime(trigger.getEndTime());
jobInfo.setJobClass(jd.getJobClass().getCanonicalName());
//jobInfo.setDuration(Long.parseLong(jd.getDescription()));
Trigger.TriggerState triggerState = quartzScheduler.getTriggerState(trigger.getKey());
jobInfo.setJobStatus(triggerState.toString());// NONE无, NORMAL正常, PAUSED暂停, COMPLETE完全, ERROR错误, BLOCKED阻塞
JobDataMap map = quartzScheduler.getJobDetail(jobKey).getJobDataMap();
if (null != map && CollectionUtils.isNotEmpty(map.keySet())) {
jobInfo.setCount(Integer.parseInt((String) map.get("count")));
jobInfo.setJobDataMap(map);
} else {
jobInfo.setJobDataMap(new JobDataMap());
}
jobInfos.add(jobInfo);
}
}
}
return jobInfos;
}
//去列表定时任务页面
@RequestMapping(value = "/goList")
public ModelAndView goList() throws Exception {
logBefore(logger, "去定时任务列表页面");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
//去编辑定时任务页面
@RequestMapping(value = "/goEdit")
public ModelAndView goEdit() throws Exception {
logBefore(logger, "去编辑定时任务页面");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
JobDetail jd = quartzScheduler.getJobDetail(jobKey);
List<CronTrigger> triggers = (List<CronTrigger>) quartzScheduler.getTriggersOfJob(jobKey);
CronTrigger trigger = triggers.get(0);
TriggerKey triggerKey = trigger.getKey();
String cron = trigger.getCronExpression();
pd.put("jobName", jobKey.getName());
pd.put("jobGroup", jobKey.getGroup());
pd.put("triggerName", triggerKey.getName());
pd.put("triggerGroupName", triggerKey.getGroup());
pd.put("cron", cron);
pd.put("clazz", jd.getJobClass().getCanonicalName());
mv.setViewName("system/tools/edit_job");
mv.addObject("pd", pd);
mv.addObject("msg", "edit");
logAfter(logger);
return mv;
}
//去新增定时任务页面
@RequestMapping(value = "/goAdd")
public ModelAndView goAdd() throws Exception {
logBefore(logger, "去新增定时任务页面");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
mv.setViewName("system/tools/edit_job");
mv.addObject("pd", pd);
mv.addObject("msg", "add");
logAfter(logger);
return mv;
}
//暂停任务
@RequestMapping(value = "/pauseJob")
@ResponseBody
public ModelAndView pauseJob() throws Exception {
logBefore(logger, "暂停任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
quartzScheduler.pauseJob(jobKey);
mv.addObject("data", "succ");
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
//恢复任务
@RequestMapping(value = "/resumeJob")
public ModelAndView resumeJob() throws Exception {
logBefore(logger, "恢复任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
quartzScheduler.resumeJob(jobKey);
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
//删除任务
@RequestMapping(value = "/deleteJob")
public ModelAndView deleteJob() throws Exception {
logBefore(logger, "删除任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
quartzScheduler.deleteJob(jobKey);
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
//立即运行任务
@RequestMapping(value = "/triggerJob")
public ModelAndView triggerJob() throws Exception {
logBefore(logger, "立即运行任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
quartzScheduler.triggerJob(jobKey);
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
logAfter(logger);
return mv;
}
//添加一个定时任务
@RequestMapping(value = "/add")
public ModelAndView add() throws Exception {
logBefore(logger, "添加定时任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String cron = (String) pd.get("cron");
String clazz = (String) pd.get("clazz");
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
String triggerName = (String) pd.get("triggerName");
String triggerGroupName = (String) pd.get("triggerGroupName");
QuartzManager.addJob(jobName, jobGroupName, triggerName, triggerGroupName, Class.forName(clazz), cron);
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
//修改一个定时任务
@RequestMapping(value = "/edit")
public ModelAndView edit() throws Exception {
logBefore(logger, "修改定时任务");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
pd = this.getPageData();
String cron = (String) pd.get("cron");
String jobName = (String) pd.get("jobName");
String jobGroupName = (String) pd.get("jobGroupName");
String triggerName = (String) pd.get("triggerName");
String triggerGroupName = (String) pd.get("triggerGroupName");
QuartzManager.modifyJobTime(jobName, jobGroupName, triggerName, triggerGroupName, cron);
mv.setViewName("system/tools/task");
mv.addObject("pd", pd);
mv.addObject("jobInfos", getSchedulerJobInfo());
logAfter(logger);
return mv;
}
}
页面代码
<table id="table_report" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<!-- th class="center">序号</th-->
<th class="center">任务组名称</th>
<th class="center">定时任务名称</th>
<!-- <th class="center">触发器组名称</th>
<th class="center">触发器名称</th> -->
<th class="center">时间表达式</th>
<th class="center">上次运行时间</th>
<th class="center">下次运行时间</th>
<th class="center">任务状态</th>
<!-- <th class="center">已经运行时间</th> -->
<!-- <th class="center">持续运行时间</th> -->
<th class="center">开始时间</th>
<th class="center">结束时间</th>
<th class="center">任务类名</th>
<!-- <th class="center">方法名称</th> -->
<!-- <th class="center">jobObject</th> -->
<!-- <th class="center">运行次数</th> -->
<th class="center">操作</th>
</tr>
</thead>
<tbody>
<!-- 开始循环 -->
<c:choose>
<c:when test="${not empty jobInfos && jobInfos.size()>0}">
<c:forEach items="${jobInfos}" var="var" varStatus="vs">
<tr>
<td class='center' style="width: auto;">${var.jobGroup}</td>
<td class='center' style="width: auto;">${var.jobName}</td>
<%-- <td class='center' style="width: auto;">${var.triggerGroupName}</td>
<td class='center' style="width: auto;">${var.triggerName}</td> --%>
<td class='center' style="width: auto;">${var.cronExpr}</td>
<td class='center' style="width: auto;"><fmt:formatDate value="${var.previousFireTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td class='center' style="width: auto;"><fmt:formatDate value="${var.nextFireTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td class='center' style="width: auto;">
<c:if test="${var.jobStatus == 'NONE'}">
<span class="label">未知</span>
</c:if>
<c:if test="${var.jobStatus == 'NORMAL'}">
<span class="label label-success arrowed">正常运行</span>
</c:if>
<c:if test="${var.jobStatus == 'PAUSED'}">
<span class="label label-warning">暂停状态</span>
</c:if>
<c:if test="${var.jobStatus == 'COMPLETE'}">
<span class="label label-important arrowed-in">完成状态</span>
</c:if>
<c:if test="${var.jobStatus == 'ERROR'}">
<span class="label label-info arrowed-in-right arrowed">错误状态</span>
</c:if>
<c:if test="${var.jobStatus == 'BLOCKED'}">
<span class="label label-inverse">锁定状态</span>
</c:if>
</td>
<%-- <td class='center' style="width: auto;">${var.runTimes}</td> --%>
<%-- <td class='center' style="width: auto;">${var.duration}</td> --%>
<td class='center' style="width: auto;"><fmt:formatDate value="${var.startTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td class='center' style="width: auto;"><fmt:formatDate value="${var.endTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td class='center' style="width: auto;">${var.jobClass}</td>
<%-- <td class='center' style="width: auto;">${var.jobMethod}</td> --%>
<%-- <td class='center' style="width: auto;">${var.jobObject}</td> --%>
<%-- <td class='center' style="width: auto;">${var.count}</td> --%>
<td class='center' style="width: auto;">
<a class="btn btn-minier btn-info" onclick="triggerJob('${var.jobName}','${var.jobGroup}');"><i class="icon-edit"></i>运行</a>
<a class="btn btn-minier btn-purple" onclick="resumeJob('${var.jobName}','${var.jobGroup}');"><i class="icon-edit"></i>恢复</a>
<a class="btn btn-minier btn-success" onclick="edit('${var.jobName}','${var.jobGroup}');"><i class="icon-edit"></i>编辑</a>
<a class="btn btn-minier btn-warning" onclick="pauseJob('${var.jobName}','${var.jobGroup}');"><i class="icon-edit"></i>暂停</a>
<a class="btn btn-minier btn-danger" onclick="deleteJob('${var.jobName}','${var.jobGroup}');"><i class="icon-edit"></i>删除</a>
</td><!-- cron,jobName,jobGroupName,triggerName,triggerGroupName -->
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr class="main_info">
<td colspan="100" class="center">没有相关数据</td>
</tr>
</c:otherwise>
</c:choose>
</tbody>
</table>
Quartz实战的更多相关文章
- SpringBoot之Quartz实战
说明:由于上篇文章我们已经讨论过springboot整合Quartz及相关配置,本次我们只说明Qrtz的增.删.改.启动.停止相关api的使用,其中涉及的其他技术,如:mybatisplus等技术以后 ...
- .NET开源作业调度框架(Quartz.NET和FluentScheduler)实战项目演练
一.课程介绍 明人不说暗话,跟着阿笨一起玩NET .本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享 ...
- Spring任务调度实战之Quartz Simple Trigger(转)
启动时执行和定时执行: 本文地址:http://blog.csdn.net/kongxx/article/details/6751300 在spring中对任务调度的集成除了使用JDK自带的Time ...
- 开源作业调度框架 - Quartz.NET - 实战使用2
纠正第一篇文章的一个错误代码. 下面是错误代码,这样并不能得知系统中是否已经存在该JobId //实例化一个作业Key对象,用于获取作业对象或判断是否存在作业时使用. JobKey jobKey = ...
- 开源作业调度框架 - Quartz.NET - 实战使用1
简介: 第一步:下载Quartz.NET 下载Quartz.NET只需要打开网址选择适宜的版本进行下载解压缩即可. 目前最新版本是2.3.3,压缩包为6MB,不过鉴于国内网速.我还是加一下博客园的下载 ...
- Quartz使用(6) - Quartz项目实战
本片博文将阐述项目工作中使用Quartz的情况,包含项目背景.项目框架.Quartz集群部署等方面,重点讲述如何在实际项目中使用Quartz. 1. 背景 因项目需求,需要定时调用数据下载接口,并将数 ...
- Spring任务调度实战之Quartz Cron Trigger
在Quartz中除了使用最简单的Simple Trigger以外,也可以使用类似Linux上Cron作业的CronTrigger的方式来运行Job,下面是一个小例子: 1. 首先是一个任务类,这个类没 ...
- Net作业调度(一) -Quartz.Net入门
背景 很多时候,项目需要在不同时刻,执行一个或很多个不同的作业. Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架. 介绍 Quartz一个开源 ...
- 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)
轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...
随机推荐
- Luca Canali
https://github.com/LucaCanali http://cern.ch/canali/
- 安装elasticsearch遇到的签名和目标被配置多次的问题
命中:6 http://ppa.launchpad.net/ondrej/php/ubuntu bionic InRelease获取:7 http://packages.elastic.co/elas ...
- Java 实现代理(Proxy)模式
类图 /** * 游戏者接口 * @author stone * */ public interface IGamePlayer { // 登录游戏 public void login(String ...
- Reduce 任务的完整数据流
- UVA 23 out of 5
题目例如以下: Problem I 23 Out of 5 Input: standard input Output: standardoutput Time Limit: 1 second Memo ...
- 极客标签互动课程系列 - Javascript生成SVG动画素描特效
课程描写叙述:在这个课程中,我们将介绍SVG.而且介绍怎样使用javascript来控制SVG生成素描动画效果 课程地址:http://www.gbtags.com/gb/gbliblist/21.h ...
- automaticallyAdjustsScrollViewInsets 使用
automaticallyAdjustsScrollViewInsets(个人认为iOS7中略坑爹的属性) @当我们在一个UIViewController中同时创建2个tableView的时候,如果把 ...
- CoffeeScript的缩进
CoffeeScript用缩进代替了花括符"{}",作用范围的划分只靠缩进.这带来代码精简.简洁的同时,有时候也让人困惑. 比如说: if 3 > 1 alert(" ...
- [水题]4242 果实计数&&3214 采访对象
4242 果实计数 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 淘淘家有棵奇怪的苹果树,这棵树共有n+1层 ...
- ios3--UIView的常见方法
// // ViewController.m // 07-UIView的常见方法 // #import "ViewController.h" @interface ViewCont ...