前言

该系统使用场景:

在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. Python菜鸟快乐游戏编程_pygame(5)

    Python菜鸟快乐游戏编程_pygame(博主录制,2K分辨率,超高清) https://study.163.com/course/courseMain.htm?courseId=100618802 ...

  2. easyExcel导出excel的简单使用

    easyExcel导出excel的简单使用 Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定 ...

  3. [Reinforcement Learning] Model-Free Prediction

    上篇文章介绍了 Model-based 的通用方法--动态规划,本文内容介绍 Model-Free 情况下 Prediction 问题,即 "Estimate the value funct ...

  4. IntelliJ IDEA中项目报错org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 8 或maven操作compile报resource使用utf8这样的编码错

    问题:项目开发工具已经setting成utf-8 并且项目各方面的配置文件包括maven这些的pom.xml里的配置都已经设置为utf-8 但是还报错 IntelliJ IDEA中项目报错org.xm ...

  5. 通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明

    通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明 错误原因是springmvc中的约束信息不对 <beans xmlns="http://w ...

  6. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  7. Python3 指定文件夹下所有文件(包括子目录下的文件)拷贝到目标文件夹下

    #!/usr/bin/env python3 # -*- coding:utf8 -*- # @TIME :2018/9/17 9:02 # @Author:dazhan # @File :copyf ...

  8. JAVA_Sprint学习(一)

    保存用户信息的编程思维 传统的思想,就是建立一个类之后,然后将用户的姓名和密码,以及添加用户等操作都放在一个main中, 按照抽象编程的思想而言, 首先建立一个类User,用来是表示用户的具体信息Us ...

  9. 利用C# 窗体设计 写一个抽奖游戏

    老师布置了一个任务,要求我们做一个抽奖游戏,以下是我个人制作的一个作品与写项目的过程. 我们用到了8个pictureBox控件和一个button,设置好大小,并且编排成一个九宫个形状 添加窗体的背景图 ...

  10. 项目Alpha冲刺(团队)-第一天冲刺

    格式描述 课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(团队)-代码规范.冲刺任务与计划 团队名称:为了交项目干杯 作业目标:描述第一天冲刺的项目进展.问题困难.心得体会 ...