前言

该系统使用场景:

在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. (一)V4L2学习流程

    title: V4L2学习流程 date: 2019/4/23 18:00:00 toc: true --- V4L2学习流程 参考资料 关键资料,插图让人一下子就理解了 Linux摄像头驱动1--v ...

  2. 07--STL序列容器(Array)

    一:Array了解 array<T,N> 模板定义了一种相当于标准数组的容器类型.它是一个有 N 个 T 类型元素的固定序列.除了需要指定元素的类型和个数之外,它和常规数组没有太大的差别. ...

  3. GIT-windows系统下Gitblit的使用方式

    GIT-windows系统下Gitblit的正确打开方式 1. 打开页面. 在配置好Gitblit后,打开可视化界面. 2. 创建用户 点击右上角添加用户,进入明细页面,填写常规信息. 创建用户(账号 ...

  4. C++预编译头文件 – stdafx.h

    预编译头文件的由来 也许请教了别的高手之后,他们会告诉你,这是预编译头,必须包含.可是,这到底是为什么呢?预编译头有什么用呢? 咱们从头文件的编译原理讲起.其实头文件并不神秘,其在编译时的作用,就是把 ...

  5. 提取 linux 文件目录结构

    提取 linux  文件的目录结构 find /home/user1/ -type d |while read line ;do mkdir -p /home/user2/$line;done

  6. 错误:org.springframework.jdbc.support.SQLErrorCodesFactory - SQLErrorCodes loaded

    使用spring+mybatis整合时报错:org.springframework.jdbc.support.SQLErrorCodesFactory - SQLErrorCodes loaded 错 ...

  7. CodeChef - COUNTREL Count Relations

    题目链接 给你一个长为NNN的1,2,3,....N1,2,3,....N1,2,3,....N的序列,让你求出两种关系各个有多少可能: R1R_1R1​,由于x,yx,yx,y互不是子集,且交集为空 ...

  8. SpringMVC+Apache Shiro+JPA(hibernate)案例教学(四)基于Shiro验证用户权限,且给用户授权

    最新项目比较忙,写文章的精力就相对减少了,但看到邮箱里的几个催更,还是厚颜把剩下的文档补上. 一.修改ShiroDbRealm类,实现它的doGetAuthorizationInfo方法 packag ...

  9. sql的四种匹配模式

    1. % 表示任意0个或多个字符.如下语句:Select * FROM user Where name LIKE '%三%'; 将会把name为“张三”,“三脚猫”,“唐三藏”等等有“三”的全找出来. ...

  10. 【转】Python多进程编程

    [转]Python多进程编程 序. multiprocessingpython中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Pytho ...