- Quartz+WeChat公众号消息推送
- POM依赖
- application.properties
- Bean(Quartz所需要的参数)
- config
- util(工具类)
- Job
- service
- controller层
- controller(测试)
- Job(测试)
- 测试成功
- corn表达式
提示:根据具体需求进行更改:
工具jdk1.8版本以上+IDEA(Springboot+Maven)
POM依赖application.properties4.0.0 org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE com.example war fisJob 0.0.1-SNAPSHOT fisJob fis定时任务 8 org.quartz-scheduler quartz 2.3.0 org.springframework spring-context-support org.springframework spring-tx 4.1.6.RELEASE org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web javax.servlet javax.servlet-api 3.1.0 provided org.apache.httpcomponents httpclient 4.5.10 net.sf.json-lib json-lib 2.4 jdk15 org.springframework.boot spring-boot-maven-plugin 2.0.3.RELEASE spring-milestones Spring Milestones https://repo.spring.io/milestone false spring-milestones Spring Milestones https://repo.spring.io/milestone false
server.port=8080 ####################### quartz设置 ############################# #线程池实现类,可以自定义,org.quartz.simpl.SimpleThreadPool是quartz自带的。 spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool #可用于并发执行作业的线程数 spring.quartz.properties.org.quartz.threadPool.threadCount=10 #线程权限值,1-10,默认为5 spring.quartz.properties.org.quartz.threadPool.threadPriority=5 #用来设置调度引擎对触发器超时的忍耐时间,有可能任务触发时线程池已满或者调度挂了,但不超过这个时间就不算超时。 spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000 #微信公众号信息 wechat.appid= wechat.secret=Bean(Quartz所需要的参数)
提示:任务、任务分钟、触发器、触发器组名称都需要唯一, 周期任务结束时间建议设为当天晚上23:59:59
package com.example.fisJob.bean;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
public class CronTask implements Serializable {
private static final long serialVersionUID = 7_899_761_044_300_053_771L;
private String jobName;
private String jobGroupName;
private String triggerName;
private String triggerGroupName;
private String cron;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date startDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date endDate;
private Map paramMap;
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobGroupName() {
return jobGroupName;
}
public void setJobGroupName(String jobGroupName) {
this.jobGroupName = jobGroupName;
}
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 getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Map getParamMap() {
return paramMap;
}
public void setParamMap(Map paramMap) {
this.paramMap = paramMap;
}
}
config
JobFactory
package com.example.fisJob.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component
public class JobFactory extends AdaptableJobFactory{
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 实例化对象
Object jobInstance = super.createJobInstance(bundle);
// 进行注入(Spring管理该Bean)
capableBeanFactory.autowireBean(jobInstance);
//返回对象
return jobInstance;
}
}
QuartzConfig
package com.example.fisJob.config;
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class QuartzConfig {
private JobFactory jobFactory;
public QuartzConfig(JobFactory jobFactory) {
this.jobFactory = jobFactory;
}
@Bean(name="SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() {
// Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 设置自定义Job Factory,用于Spring管理Job bean
factory.setJobFactory(jobFactory);
return factory;
}
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
util(工具类)
package com.example.fisJob.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.UnsupportedCharsetException;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpInteractionUtil {
private static Logger logger = LoggerFactory.getLogger(HttpInteractionUtil.class);
public static String executeHttpPost(String url,String json){
try {
//建立连接
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.addHeader("Content-Type","application/json");
//内容
StringEntity entity = new StringEntity(json, ContentType.create("application/json", "utf-8"));
post.setEntity(entity);
//执行
CloseableHttpResponse resp = client.execute(post);
//返回
int sc = resp.getStatusLine().getStatusCode();
if(sc>=200 && sc<300) {
return EntityUtils.toString(resp.getEntity());
}
} catch (UnsupportedCharsetException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String executeHttpGet(String url){
try {
//建立连接
CloseableHttpClient client = HttpClients.createDefault();
HttpGet get = new HttpGet(url);
CloseableHttpResponse resp = client.execute(get);
int statusCode = resp.getStatusLine().getStatusCode();
if(statusCode>=200 && statusCode<300) {
HttpEntity entity = resp.getEntity();
return EntityUtils.toString(entity,"utf-8");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String getDate(String rcwUrl, String enc) {
StringBuffer strBuf = new StringBuffer();
try {
logger.error("发送http请求url:"+rcwUrl);
URL url = new URL(rcwUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), enc));
for (String line = null; (line = reader.readLine()) != null;)
strBuf.append((new StringBuilder(String.valueOf(line))).append(" ").toString());
reader.close();
} catch (MalformedURLException malformedurlexception) {
logger.error("发送http请求MalformedURL异常:"+malformedurlexception.getMessage());
} catch (IOException ioexception) {
logger.error("发送http请求IO异常2:"+ioexception.getMessage());
}
return strBuf.toString();
}
public static String getDateByPost(String rcwUrl, String enc) {
StringBuffer strBuf = new StringBuffer();
try {
URL url = new URL(rcwUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("post"); //请求方式
connection.setReadTimeout(2000); //读取数据超时
connection.setDoOutput(true);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), enc));
for (String line = null; (line = reader.readLine()) != null;)
strBuf.append((new StringBuilder(String.valueOf(line))).append(" ").toString());
reader.close();
} catch (MalformedURLException malformedurlexception) {
} catch (IOException ioexception) {
}
return strBuf.toString();
}
}
Job
package com.example.fisJob.job;
import com.example.fisJob.util.HttpInteractionUtil;
import net.sf.json.JSONObject;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class WechatMsgJob implements Job {
@Value("${wechat.appid}")
private String appid;
@Value("${wechat.secret}")
private String secret;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Map map=jobExecutionContext.getJobDetail().getJobDataMap();
String token =this.getToken();
// 接口地址
String sendMsgApi = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+token;
//消息模板ID
String template_id = map.get("templateId").toString();
//整体参数map
JSONObject param = new JSONObject();
//消息主题显示相关map
Map data = (Map) map.get("data");
String openId=map.get("openId").toString();
param.put("touser", openId);
param.put("template_id", template_id);
param.put("data", data);
String result=HttpInteractionUtil.executeHttpPost(sendMsgApi,param.toString());
System.out.println(result);
}
private String getToken() {
// 接口地址拼接参数
String getTokenApi = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid
+ "&secret=" + secret;
String tokenJsonStr = HttpInteractionUtil.executeHttpGet(getTokenApi);
JSONObject tokenJson=JSONObject.fromObject(tokenJsonStr);
String token = tokenJson.get("access_token").toString();
return token;
}
}
service
package com.example.fisJob.service;
import com.example.fisJob.bean.CronTask;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class QuartzManager {
private static Logger logger = LoggerFactory.getLogger(QuartzManager.class);
@Autowired
private Scheduler scheduler;
public void addJob(CronTask cronTask, Class clazz ) {
try {
// 任务名,任务组,任务执行类
JobDetail jobDetail= JobBuilder.newJob(clazz).withIdentity(cronTask.getJobName(), cronTask.getJobGroupName())
.build();
// 任务参数
jobDetail.getJobDataMap().putAll(cronTask.getParamMap());
// 触发器
TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(cronTask.getTriggerName(), cronTask.getTriggerGroupName());
// 触发器生效时间
if(null!=cronTask.getStartDate()){
triggerBuilder.startAt(cronTask.getStartDate());
}else {
triggerBuilder.startNow();
}
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronTask.getCron()));
// 触发器失效时间
if(null!=cronTask.getEndDate()){
triggerBuilder.endAt(cronTask.getEndDate());
}
// 创建Trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 调度容器设置JobDetail和Trigger
scheduler.scheduleJob(jobDetail, trigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void modifyJobTime(String jobName,
String jobGroupName, String triggerName, String triggerGroupName, String cron) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
// 触发器
TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一个任务的触发时间
scheduler.rescheduleJob(triggerKey, trigger);
//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);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void removeJob(CronTask cronTask) {
try {
List triggerGroupNames = scheduler.getTriggerGroupNames();
TriggerKey triggerKey = TriggerKey.triggerKey(cronTask.getTriggerName(), cronTask.getTriggerGroupName());
scheduler.pauseTrigger(triggerKey);// 停止触发器
scheduler.unscheduleJob(triggerKey);// 移除触发器
scheduler.deleteJob(JobKey.jobKey(cronTask.getJobName(), cronTask.getJobGroupName()));// 删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void startJobs() {
try {
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void shutdownJobs() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void safeShutdown() throws SchedulerException {
int executingJobSize = scheduler.getCurrentlyExecutingJobs().size();
logger.info("安全关闭 当前还有" + executingJobSize + "个任务正在执行,等待完成后关闭");
//等待任务执行完后安全关闭
scheduler.shutdown(true);
logger.info("安全关闭 成功");
}
}
controller层
可以将WechatFiveMsgJob.class替换成自己所写的
package com.example.fisJob.controller;
import com.example.fisJob.bean.CronTask;
import com.example.fisJob.job.RuleTriggerJob;
import com.example.fisJob.job.TestJob;
import com.example.fisJob.job.WechatFiveMsgJob;
import com.example.fisJob.job.WechatMsgJob;
import com.example.fisJob.service.QuartzManager;
import com.example.fisJob.util.HttpInteractionUtil;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;
@EnableAutoConfiguration
@RestController
@RequestMapping("/wechat")
public class WechatController {
@Autowired
private QuartzManager quartzManager;
@PostMapping("/addjob")
public String addjob(@RequestBody CronTask cronTask) {
JSONObject resul=new JSONObject();
try {
System.out.println(cronTask.getCron());
System.out.println(cronTask.getJobName());
quartzManager.addJob(cronTask, WechatFiveMsgJob.class);
resul.put("flag",true);
resul.put("msg","添加任务成功");
}catch (Exception e){
e.printStackTrace();
resul.put("flag",false);
resul.put("msg","添加任务失败");
}
return resul.toString();
}
@PostMapping("/removejob")
public String removejob(@RequestBody CronTask cronTask) {
JSONObject resul=new JSONObject();
try {
quartzManager.removeJob(cronTask);
resul.put("flag",true);
resul.put("msg","删除任务成功");
}catch (Exception e){
e.printStackTrace();
resul.put("flag",false);
resul.put("msg","删除任务失败");
}
return resul.toString();
}
}
controller(测试)
package com.example.fisJob.controller;
import com.example.fisJob.bean.CronTask;
import com.example.fisJob.job.RuleTriggerJob;
import com.example.fisJob.service.QuartzManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private QuartzManager quartzManager;
@GetMapping("/addJob")
public String addjob(@RequestParam int index) {
Map paramMap=new HashMap<>();
paramMap.put("name","Sunrise");
paramMap.put("index",index);
CronTask cronTask=new CronTask();
cronTask.setJobName("testJob"+index);
cronTask.setJobGroupName("testJobGroup");
cronTask.setTriggerName("testTrigger"+index);
cronTask.setTriggerGroupName("testTriggerGroup");
cronTask.setCron("10/11 * * * * ? ");
cronTask.setStartDate(new Date());
Calendar cal=Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.SECOND,100);
cronTask.setEndDate(cal.getTime());
cronTask.setParamMap(paramMap);
quartzManager.addJob(cronTask, RuleTriggerJob.class);
return "定时任务启动成功";
}
@GetMapping("/delJob")
public String deljob() {
CronTask cronTask=new CronTask();
cronTask.setJobName("testJob1");
cronTask.setJobGroupName("testJobGroup");
cronTask.setTriggerName("testTrigger1");
cronTask.setTriggerGroupName("testTriggerGroup");
quartzManager.removeJob(cronTask);
return "定时任务关闭成功";
}
}
Job(测试)
package com.example.fisJob.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
@Component
public class RuleTriggerJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println(new Date() + "定时任务执行");
Map map=jobExecutionContext.getJobDetail().getJobDataMap();
String name=map.get("name").toString();
int age=Integer.parseInt(map.get("age").toString());
int index=Integer.parseInt(map.get("index").toString());
System.out.println("我的名字是:"+name+";我是线程:"+index);
}
}
测试成功
corm表达式
人要成长,必有原因,背后的努力与积累一定数倍于普通人,所以,关键还在于自己。 —— 杨绛



