前言

该系统使用场景:

在12306上买了一张火车票,30分钟内需要支付(需要添加一个倒计时),30分钟还没有支付就请求取消订单的接口(自动根据url请求),如果支付了收到了支付的回调通知后,就删除计时器上的该任务

1.项目结构图

2.引入所需要依赖的jar包

<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency> <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.ezmorph/ezmorph -->
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>

3.编写以下类:

  3.1Config.java

    

public class Config {
public static String token="liujun";
private Config() {
super();
}
}

  3.2  JobGroupInfo.java

    

public class JobGroupInfo {
private String jobName;//任务名字
private String jobGroupName;//组名字
private Long nextFireTime;//下次执行时间 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 Long getNextFireTime() {
return nextFireTime;
} public void setNextFireTime(Long nextFireTime) {
this.nextFireTime = nextFireTime;
}
public JobGroupInfo() {
super();
}
public JobGroupInfo(String jobName, String jobGroupName, Long nextFireTime) {
super();
this.jobName = jobName;
this.jobGroupName = jobGroupName;
this.nextFireTime = nextFireTime;
}
}

  3.3  TaskInfo.java

    

public class TaskInfo {
private String backUrl;//任务回调地址
private String jobName;//任务名字
private Integer seconds;//计时时间
private Object context;//其他内容
private Integer errormaxcount;//失败请求的次数
private String jobGorupName;//任务组名字 public String getBackUrl() {
return backUrl;
} public void setBackUrl(String backUrl) {
this.backUrl = backUrl;
} public String getJobName() {
return jobName;
} public void setJobName(String jobName) {
this.jobName = jobName;
} public Integer getSeconds() {
return seconds;
} public void setSeconds(Integer seconds) {
this.seconds = seconds;
} public Object getContext() {
return context;
} public void setContext(Object context) {
this.context = context;
} public Integer getErrormaxcount() {
return errormaxcount;
} public void setErrormaxcount(Integer errormaxcount) {
this.errormaxcount = errormaxcount;
} public String getJobGorupName() {
return jobGorupName;
} public void setJobGorupName(String jobGorupName) {
this.jobGorupName = jobGorupName;
}
public TaskInfo() {
super();
}
public TaskInfo(String backUrl, String jobName, Integer seconds,
Object context, Integer errormaxcount, String jobGorupName) {
super();
this.backUrl = backUrl;
this.jobName = jobName;
this.seconds = seconds;
this.context = context;
this.errormaxcount = errormaxcount;
this.jobGorupName = jobGorupName;
}
@Override
public String toString() {
return "TaskInfo [backUrl=" + backUrl + ", jobName=" + jobName
+ ", seconds=" + seconds + ", context=" + context
+ ", errormaxcount=" + errormaxcount + ", jobGorupName="
+ jobGorupName + "]";
}
}

  3.4 JobBack.java

    

public class JobBack implements Job{
//回调执行方法
public void execute(JobExecutionContext context) throws JobExecutionException {
//得到添加任务中的参数
TaskInfo task = (TaskInfo) context.getMergedJobDataMap().get("task");
sendBack(task);
} private void sendBack(TaskInfo task) {
task.setErrormaxcount(task.getErrormaxcount() - 1);
// 得到参数请求回调
try {
//拼装请求地址以及参数
String uri = "jobName=" + task.getJobName() + "&context=" + task.getContext() + "&jobGorupName="
+ task.getJobGorupName() + "&paramkey=" + Md5Util.GetMD5Code(Config.token);
//请求并得到返回值
String res = HttpUtil.request_post(task.getBackUrl(), uri);
//如果返回值不是“SUCCESS” 就等待10S进行重复请求(此处避免请求失败就结束请求,参数中传递了一个失败请求次数)
if (!res.trim().equals("SUCCESS")) {
//如果请求错误次数还大于0
if (task.getErrormaxcount() >= 1) {
Thread.sleep(10000);
sendBack(task);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
if (task.getErrormaxcount() >= 1) {
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
sendBack(task);
}
}
}
}

  3.5 JobManger.java

    

public class JobManger {
private final static String TRIGGER_GROUP_NAME = "QUARTZ_TRIGGERGROUP";//触发器组
private final static SchedulerFactory sf = new StdSchedulerFactory();
/**
* 添加任务
* @param jobName 任务名称
* @param job 任务处理类 需要继承Job
* @param context 处理任务可以获取的上下文 通过context.getMergedJobDataMap().getString("context"); 获取
* @param seconds 间隔秒
* @return
*/
public static int addJob(String jobName, Class<? extends Job> job, Object task, int seconds, String jobGorupName){
try {
//判断任务是否存在
Scheduler sche = sf.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName,jobGorupName);
if(sche.checkExists(jobKey)){
return 1;//任务已经存在
}
//创建一个JobDetail实例,指定SimpleJob
Map<String, Object> JobDetailmap =new HashMap<String, Object>();
JobDetailmap.put("name", jobName);//设置任务名字
JobDetailmap.put("group", jobGorupName);//设置任务组
JobDetailmap.put("jobClass",job.getCanonicalName());//指定执行类 Task.class.getCanonicalName()
JobDetail jobDetail= JobDetailSupport.newJobDetail(JobDetailmap);
//添加数据内容
jobDetail.getJobDataMap().put("task",task);//传输的上下文
//通过SimpleTrigger定义调度规则:马上启动,每2秒运行一次,共运行100次 等。。。。
SimpleTriggerImpl simpleTrigger = new SimpleTriggerImpl();
simpleTrigger.setName(jobName);
simpleTrigger.setGroup(TRIGGER_GROUP_NAME);
//什么时候开始执行
simpleTrigger.setStartTime(new Date(new Date().getTime()+1000*seconds));
//间隔时间
simpleTrigger.setRepeatInterval(1000*seconds);
//最多访问次数 默认执行一次
simpleTrigger.setRepeatCount(0);
//通过SchedulerFactory获取一个调度器实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.scheduleJob(jobDetail, simpleTrigger);//④ 注册并进行调度
scheduler.start();//⑤调度启动
return 0;//添加成功
} catch (Exception e) {
return 2;//操作异常
}
}
/**
* 关闭任务调度
* @param jobName 任务名称
* @return 0 关闭成功 1: 关闭失败 2:操作异常
*/
public static int closeJob(String jobName,String jobGorupName){
//关闭任务调度
try {
Scheduler sche = sf.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName,jobGorupName);
return sche.deleteJob(jobKey)==true?0:1;
} catch (SchedulerException e) {
return 2;
}
}
private JobManger() {}
}

  3.6 AddJob.java

    

@WebServlet("/addJob.do")
public class AddJob extends HttpServlet{
private static final long serialVersionUID = 1L; public AddJob() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//避免get 请求
response.sendError(403);
// doPost(request, response);
} /**
* 处理添加任务
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置编码
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("utf-8");
// 得到请求
String jobName = request.getParameter("jobName");// 得到任务名称
// 得到token
//String token = request.getParameter("token");
// 验证签名
/*if (!MD5Util.GetMD5Code(jobName + Config.token + "zhangke is shabi!").equals(token)) {
return;
}*/
// 得到回调
String backUrl = request.getParameter("backUrl");
// 得到请求定时时间
Integer seconds = Integer.valueOf(request.getParameter("seconds"));
String errMaxCount = request.getParameter("errormaxcount");
Integer errormaxcount = errMaxCount == null ? 1 : Integer.valueOf(errMaxCount);// 回调请求失败的次数
// 默认为一次
// 得到其他参数
String context = request.getParameter("context");
// 得到任务组
String jobGorupName = request.getParameter("jobGorupName"); TaskInfo t = new TaskInfo(backUrl, jobName, seconds, context, errormaxcount, jobGorupName);
// 添加任务
Integer res = JobManger.addJob(jobName, JobBack.class, t, seconds, jobGorupName);
response.getWriter().write(res.toString());
}
}

  3.7 MonitoringJob.java

    

@WebServlet("/monitoringJob.do")
public class MonitoringJob extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public MonitoringJob() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
} protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/json;char=utf-8");
// 得到任务组名字
String jobGroupName = request.getParameter("jobGroupName");
// 验证是否为空
//monitoringJob.do
List<JobGroupInfo> list=new ArrayList<JobGroupInfo>();
try {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(jobGroupName==null?"":jobGroupName))) {
String jobName = jobKey.getName();
String jobGroup = jobKey.getGroup();
// get job's trigger
List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
Date nextFireTime = triggers.get(0).getNextFireTime(); // 下一次执行时间、
JobGroupInfo gri=new JobGroupInfo(jobName, jobGroup, nextFireTime.getTime());
list.add(gri);
}
response.getWriter().write(JSONArray.fromObject(list).toString());
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

  3.8 RemoveJob.java

    

@WebServlet("/removeJob.do")
public class RemoveJob extends HttpServlet {
private static final long serialVersionUID = 1L; public RemoveJob() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(403);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到任务名
String jobName=request.getParameter("jobName");
//得到签名
String token =request.getParameter("token");
//得到任务组
String jobGorupName=request.getParameter("jobGorupName");
//验证签名
/*if(!MD5Util.GetMD5Code(jobName+Config.token+"zhangke is sb!").equals(token)){
response.getWriter().write("2");
return;
}*/
//执行移除操作
int res= JobManger.closeJob(jobName,jobGorupName);
if(res==0){//成功
response.getWriter().write("0");
}else if(res==1){//不存在
response.getWriter().write("1");
}else{
//报错啦!
response.getWriter().write("2");
}
}
}

  3.9 TestBack.java

    

@WebServlet("/testback")
public class TestBack extends HttpServlet {
private static final long serialVersionUID = 1L; public TestBack() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("get请求");
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
Map<String, String[]> map=request.getParameterMap();
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
String key=iter.next();
System.out.println("key:"+key+" value:"+map.get(key)[0]);
}
response.getWriter().write("SUCCESS");
}
}

  3.10 HttpUtil.java

    

public class HttpUtil {
public static String request_get(String httpUrl) {
BufferedReader reader = null;
String result = null;
StringBuffer sbf = new StringBuffer(); try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(20000);
connection.connect();
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();
result = sbf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static String request_post(String httpUrl, String httpArg) {
BufferedReader reader = null;
String result = null;
StringBuffer sbf = new StringBuffer(); try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(20000);
connection.getOutputStream().write(httpArg.getBytes("UTF-8"));
connection.connect();
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();
result = sbf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

  3.11 Md5Util.java

public class Md5Util {
private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; public Md5Util() {
} private static String byteToArrayString(byte bByte) {
int iRet = bByte;
if (iRet < 0) {
iRet += 256;
}
int iD1 = iRet / 16;
int iD2 = iRet % 16;
return strDigits[iD1] + strDigits[iD2];
} private static String byteToNum(byte bByte) {
int iRet = bByte;
System.out.println("iRet1=" + iRet);
if (iRet < 0) {
iRet += 256;
}
return String.valueOf(iRet);
} private static String byteToString(byte[] bByte) {
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < bByte.length; i++) {
sBuffer.append(byteToArrayString(bByte[i]));
}
return sBuffer.toString();
} public static String GetMD5Code(String strObj) {
String resultString = null;
try {
resultString = new String(strObj);
MessageDigest md = MessageDigest.getInstance("MD5");
resultString = byteToString(md.digest(strObj.getBytes()));
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
return resultString;
}
} 4.启动maven
https://blog.csdn.net/nandao158/article/details/809021935.测试 postman

5秒后看控制台


Quartz+JAVA+Servlet实现任务调度系统(简洁)的更多相关文章

  1. Quartz任务调度系统,克隆表达式

    Quartz任务调度系统,克隆表达式 (1).克隆表达式可以包括7个字段:秒.分.小时.月内日期.月.周内日期.年(可选字段) (2).特殊字符: 一.反斜线(/)字符表示增量."5/15& ...

  2. 聊Java中的任务调度的实现方法及比较

    前言 任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务.本文由浅入深介绍四种任务调度的 Java 实现: Timer ScheduledExecutor 开源工具包 Quartz ...

  3. 分布式任务调度系统xxl-job搭建

    为解决分布式环境下定时任务的可靠性,稳定性,只执行一次的特性,我找到了个大众点评开源的分布式调度任务解决完整系统,下面我将一步步深入解读该系统,从基本的使用到源码的探究 下载 https://gith ...

  4. 分布式定时任务调度系统技术解决方案(xxl-job、Elastic-job、Saturn)

    1.业务场景 保险人管系统每月工资结算,平安有150万代理人,如何快速的进行工资结算(数据运算型) 保险短信开门红/电商双十一 1000w+短信发送(短时汇聚型) 工作中业务场景非常多,所涉及到的场景 ...

  5. Java Servlet与Web容器之间的关系

    自从计算机软件开发进入网络时代,就开始涉及到通讯问题.在客户/服务器(也叫C/S应用)时期,每个软件都有自己的客户端和服务器端软件.并且客户端和服务器端之间的通讯协议差别也很大.后来随着互联网的发展, ...

  6. java servlet+oracle 新手可看

    最近公司领导告诉接下去接的一个产品,可能会涉及到oracle数据库,以前用得最多的是mssql,前些时间学了下mysql也算少许用过.oracle没接触过.应为我之前做过.net开发,所以数据访问接口 ...

  7. linux 任务调度 系统任务调度

    linux  at 针对运行一次的任务 crontab   控制计划任务的命令 crond系统服务 crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程, 与windows ...

  8. Java Servlet 技术简介

    Java Servlet 技术简介 Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么 ...

  9. 【Java】Java Servlet 技术简介

    Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么,它们是如何工作的,如何使用它们来创 ...

随机推荐

  1. Intellij IDEA项目包分层结构显示设置

    问题:(这种方式的查看包名,确实十分难看) 解决方法:

  2. js制作可拖拽可点击的悬浮球

    兼容mouse事件和touch事件,支持IE9及其以上 效果展示:https://jsfiddle.net/shifeng/7xebf3u0/ // index.html <!DOCTYPE h ...

  3. Mybatis多表链接查询重复字段问题

    A表和B表一对多的关系 A表 B表 A表和C表也是一对多关系 C表 我现在向查询出A表的所有字段和B表的name字段,C表的name字段 这是我错误的sql语句,可以看出我没有查B表和C表的id字段, ...

  4. struts2 s2-032漏洞分析

    0x01Brief Description 最近面试几家公司,很多都问到了s2漏洞的原理,之前调试分析过java反序列化的漏洞,觉得s2漏洞应该不会太难,今天就分析了一下,然后发现其实漏洞的原理不难, ...

  5. pandas基础用法

    首先生成一维数组 data = pd.Series([1,2,3,4,5,6,7,8,9])data运行结果 data.head()#默认取前五条,当然也可以加参数 data.tail()#默认取前五 ...

  6. 3D Slicer中文教程(七)—图像中值滤波

    1.中值滤波概念 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘 ...

  7. zynq DMA控制器

    Zynq-7000系列器件PS端的DMA控制器采用ARM的IP核DMA-330(PL-330)实现. 特点: 1.8个独立的通道,4个可用于PL—PS间数据管理,每个通道有1024Byte的MFIFO ...

  8. tftp--实现服务器与客户端的下载与上传【转】

    转自:https://blog.csdn.net/xiaopangzi313/article/details/9122975 版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...

  9. Virtual Machine

    之前说到可以使用Assembly language来实现程序编写,把程序通过一个Assembler就可以得到计算机可以操作的二进制文件. 但是Assembly language依旧不适于编程,但怎么将 ...

  10. .net core WebAPI 初探及连接MySQL

    1. 前言 笔者最近跟着微软官方文档学习.net core WebAPI,但发现其对 WebAPI 连接数据库.读取数据库方面讲得不够细致明了.写此文的目的,即实现 .net core WebAPI ...