使用Quartz 2.2.3開啟定時任務谭期,每個整點獲取一次仅炊,如下:
String jobName = "GetWeixinAccessToken";
String triggerName = jobName;
// 每個整點執(zhí)行一次
quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);
QuartzManager使用Spring注入:
import java.util.Date;
import java.util.List;
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.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;
@Service
public class QuartzManager {
public static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
public void addJob(String jobName, String triggerName,
Class jobClass, String cron, Object obj) {
try {
Scheduler sched = schedulerFactory.getScheduler();
// 任務名跑杭,任務組嚷那,任務執(zhí)行類
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(jobName).build();
jobDetail.getJobDataMap().put("obj", obj);
// 觸發(fā)器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
.newTrigger();
// 觸發(fā)器名
triggerBuilder.withIdentity(triggerName);
triggerBuilder.startNow();
// 觸發(fā)器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 創(chuàng)建Trigger對象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 調度容器設置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
// 啟動
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 添加一個定時任務
*
* @param jobName 任務名
* @param jobGroupName 任務組名
* @param triggerName 觸發(fā)器名
* @param triggerGroupName 觸發(fā)器組名
* @param jobClass 任務
* @param cron 時間設置,參考quartz說明文檔
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class jobClass, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
// 任務名压真,任務組,任務執(zhí)行類
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 觸發(fā)器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發(fā)器名,觸發(fā)器組
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 觸發(fā)器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 創(chuàng)建Trigger對象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 調度容器設置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
// 啟動
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 修改任務的觸發(fā)時間
* @param jobName
* @param triggerName
* @param cron
*/
public void modifyJobTime(String jobName, String triggerName,
String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一 :調用 rescheduleJob 開始 */
// 觸發(fā)器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
.newTrigger();
// 觸發(fā)器名,觸發(fā)器組
triggerBuilder.withIdentity(triggerName);
triggerBuilder.startNow();
// 觸發(fā)器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder
.cronSchedule(cron));
// 創(chuàng)建Trigger對象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一個任務的觸發(fā)時間
sched.rescheduleJob(triggerKey, trigger);
/** 方式一 :調用 rescheduleJob 結束 */
/** 方式二:先刪除蘑险,然后在創(chuàng)建一個新的Job */
// JobDetail jobDetail =
// sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
// Class<? extends Job> jobClass = jobDetail.getJobClass();
// removeJob(jobName, jobGroupName, triggerName,
// triggerGroupName);
// addJob(jobName, jobGroupName, triggerName, triggerGroupName,
// jobClass, cron);
/** 方式二 :先刪除滴肿,然后在創(chuàng)建一個新的Job */
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一個任務的觸發(fā)時間
*
* @param jobName
* @param jobGroupName
* @param triggerName 觸發(fā)器名
* @param triggerGroupName 觸發(fā)器組名
* @param cron 時間設置,參考quartz說明文檔
*/
public void modifyJobTime(String jobName,
String jobGroupName, String triggerName, String triggerGroupName, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一 :調用 rescheduleJob 開始 */
// 觸發(fā)器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發(fā)器名,觸發(fā)器組
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 觸發(fā)器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 創(chuàng)建Trigger對象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一個任務的觸發(fā)時間
sched.rescheduleJob(triggerKey, trigger);
/** 方式一 :調用 rescheduleJob 結束 */
/** 方式二:先刪除佃迄,然后在創(chuàng)建一個新的Job */
//JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
//Class<? extends Job> jobClass = jobDetail.getJobClass();
//removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
//addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
/** 方式二 :先刪除泼差,然后在創(chuàng)建一個新的Job */
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一個任務
*
* @param jobName
* @param triggerName
*/
public void removeJob(String jobName, String triggerName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
sched.pauseTrigger(triggerKey);// 停止觸發(fā)器
sched.unscheduleJob(triggerKey);// 移除觸發(fā)器
sched.deleteJob(JobKey.jobKey(jobName));// 刪除任務
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一個任務
*
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public void removeJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(triggerKey);// 停止觸發(fā)器
sched.unscheduleJob(triggerKey);// 移除觸發(fā)器
sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 刪除任務
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:啟動所有定時任務
*/
public static void startJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:關閉所有定時任務
*/
public static void shutdownJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 判斷JobName是否在執(zhí)行隊列中
* @param jobName
* @return
*/
public synchronized static boolean isJobExist(String jobName) throws SchedulerException {
boolean isExistJob = false;
Scheduler scheduler = schedulerFactory.getScheduler();
for (String groupName : scheduler.getJobGroupNames()) {
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
.jobGroupEquals(groupName))) {
String tmpJobName = jobKey.getName();
String jobGroup = jobKey.getGroup();
// get job's trigger
@SuppressWarnings("unchecked")
List<Trigger> triggers = (List<Trigger>) scheduler
.getTriggersOfJob(jobKey);
Date nextFireTime = triggers.get(0).getNextFireTime();
System.out.println("[jobName] : " + tmpJobName
+ " [groupName] : " + jobGroup + " - "
+ nextFireTime);
if (tmpJobName.equals(jobName)) {
return true;
}
}
}
return isExistJob;
}
}
在Spring ApplicationContext注入后,才可獲取bean呵俏,web.xml配置攔截如下:
<!--Spring ApplicationContext 載入 -->
<listener>
<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -->
<listener-class>com.test.hello.ContextLoaderListenerOverWrite</listener-class>
</listener>
攔截類是為了獲取manager堆缘,然后存放AccessToken到數(shù)據(jù)庫中。實現(xiàn)如下:
public class ContextLoaderListenerOverWrite extends ContextLoaderListener {
@Override
public void contextInitialized(ServletContextEvent event) {
// TODO Auto-generated method stub
super.contextInitialized(event);
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
startGetWeixinAccessTokenJobs(applicationContext);
}
/**
* 開啟整點定時任務
*/
public void startGetWeixinAccessTokenJobs(ApplicationContext ctx) {
WxBean currentBean = Utility.getAccessToken();
WxAccesstoken currentToken = new WxAccesstoken();
currentToken.setAccesstoken(currentBean.getAccess_token());
currentToken.setExpiresIn(Integer.valueOf(currentBean.getExpires_in()));
currentToken.setLastRequestTime(new Date());
QuartzManager quartzManager = (QuartzManager)ctx.getBean("quartzManager");
WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)ctx.getBean("wxAccesstokenManager");
WxAccesstoken dbWxToken = wxAccesstokenManager.findFirst();
if (dbWxToken == null) { // 新增Token
wxAccesstokenManager.save(currentToken);
System.out.println("新增Token:" + currentToken);
} else { // 更新Token
currentToken.setId(dbWxToken.getId());
wxAccesstokenManager.update(currentToken);
System.out.println("更新Token:" + currentToken);
}
String jobName = "GetWeixinAccessToken";
String triggerName = jobName;
// 每個整點執(zhí)行一次
quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);
}
}
獲取微信AccessToken的辦法如下:
/**
* 獲取微信的AccessToken
* @return
*/
public static WxBean getAccessToken() {
WxBean bean = null;
Map<String, String> params = new HashMap<String, String>();
params.put("grant_type", "client_credential");
params.put("appid", Constants.WEIXIN_APPID);
params.put("secret", Constants.WEIXIN_APPSECRET);
try {
String jstoken = HttpUtils.sendGet(
"https://api.weixin.qq.com/cgi-bin/token", params);
// String access_token = JSONObject.fromObject(jstoken).getString(
// "access_token"); // 獲取到token并賦值保存
ObjectMapper objectMapper = JsonUtils.createObjectMapper();
try {
bean = objectMapper.readValue(jstoken, WxBean.class);
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bean;
}
對了普碎,還有關鍵的部分吼肥,在這個Job里面每個整點更新AccessToken
public class WeixinAccessTokenJob implements Job{
public WeixinAccessTokenJob() {
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//打印任務詳情
System.out.println( "WeixinTokenJob:" + "-" +
context.getJobDetail().getKey().getGroup()
+"——"+context.getJobDetail().getKey().getName()
+"——"+context.getTrigger().getKey().getName()
+"——"+context.getTrigger().getKey().getGroup() + new Date());
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)jobDataMap.get("obj");
// Todo 使用wxAccesstokenManager來管理數(shù)據(jù)庫存放的AccessToken
}
}