1.开发环境 tomcat8.5,Jdk1.8,maven ;技术:java ,quartz,servlet(为了简便) 2.该系统使用场景:
`在12306上买了一张火车票,30分钟内需要支付(需要添加一个倒计时),30分钟还没有支付就请求取消订单的接口(自动根据url请求),如果支付了收到了支付的回调通知后,就删除计时器上的该任务
`
3.测试环境:需要两个项目,一个为生产环境,一个为调度服务器(后边测试我只用一个调度环境,生产环境通过http请求工具模拟测试) 4.创建maven项目:JobServer ,下图是项目结构图
5.引入所需要依赖的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>
<dependency>
<groupId>commons-beanutils
</groupId>
<artifactId>commons-beanutils
</artifactId>
<version>1.9.2
</version>
</dependency>
<dependency>
<groupId>commons-collections
</groupId>
<artifactId>commons-collections
</artifactId>
<version>3.2.2
</version>
</dependency>
<dependency>
<groupId>commons-lang
</groupId>
<artifactId>commons-lang
</artifactId>
<version>2.6
</version>
</dependency>
<dependency>
<groupId>commons-logging
</groupId>
<artifactId>commons-logging
</artifactId>
<version>1.2
</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph
</groupId>
<artifactId>ezmorph
</artifactId>
<version>1.0.6
</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib
</groupId>
<artifactId>json-lib
</artifactId>
<version>2.4
</version>
</dependency>
编写以下类:
Config.java
package com.job.config;
public class Config {
public static String token=
"SB is zhangke";
private Config() {
super();
}
}
JobGroupInfo.java
package com.job.model;
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;
}
}
package com.job.model;
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
getJobGorupName() {
return jobGorupName;
}
public void setJobGorupName(String jobGorupName) {
this.jobGorupName = jobGorupName;
}
public Integer
getErrormaxcount() {
return errormaxcount;
}
public void setErrormaxcount(Integer errormaxcount) {
this.errormaxcount = errormaxcount;
}
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 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 +
"]";
}
}
JobBack.java
package com.job.server;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.job.config.Config;
import com.job.model.TaskInfo;
import com.job.utli.HttpUtil;
import com.job.utli.MD5Util;
/**
* 执行回调任务
*
* @author niewei
*
*/
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() +
"¶mkey=" + MD5Util.GetMD5Code(Config.token);
String res = HttpUtil.request_post(task.getBackUrl(), uri);
if (!res.trim().equals(
"SUCCESS")) {
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);
}
}
}
}
JobManager.java
package com.job.server;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.core.jmx.JobDetailSupport;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.SimpleTriggerImpl;
/**
* 任务调度
* @author niewei
*
*/
public class JobManager {
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;
}
Map<String, Object> JobDetailmap =
new HashMap<String, Object>();
JobDetailmap.put(
"name", jobName);
JobDetailmap.put(
"group", jobGorupName);
JobDetailmap.put(
"jobClass",job.getCanonicalName());
JobDetail jobDetail=JobDetailSupport.newJobDetail(JobDetailmap);
jobDetail.getJobDataMap().put(
"task",task);
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 =
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 JobManager() {}
}
AddJob.java
package com.job.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.job.model.TaskInfo;
import com.job.server.JobBack;
import com.job.server.JobManager;
/***
* 添加任务调度
*
* @author niewei
*
*/
@WebServlet(
"/addJob.do")
public class AddJob extends HttpServlet {
private static final long serialVersionUID =
1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AddJob() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendError(
403);
}
/**
* 处理添加任务
*/
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");
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 = JobManager.addJob(jobName, JobBack.class, t, seconds, jobGorupName);
response.getWriter().write(res.toString());
}
}
MonitoringJob.java
package com.job.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import com.job.model.JobGroupInfo;
import net.sf.json.JSONArray;
/***
* 查看任务情况
*
* @author niewei
*
*/
@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");
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();
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();
}
}
}
RemoveJob.java
package com.job.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.job.server.JobManager;
/***
* 移除任务
* @author niewei
*
*/
@WebServlet(
"/removeJob.do")
public class RemoveJob extends HttpServlet {
private static final long serialVersionUID =
1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RemoveJob() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendError(
403);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
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");
int res=JobManager.closeJob(jobName,jobGorupName);
if(res==
0){
response.getWriter().write(
"0");
}
else if(res==
1){
response.getWriter().write(
"1");
}
else{
response.getWriter().write(
"2");
}
}
}
TestBack.java(这个servlet是用来测试回调用,我回调url就写这个。。)
package com.job.servlet;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import com.fasterxml.jackson.databind.util.JSONPObject;
/**
* 测试回调地址
*/
@WebServlet(
"/testback")
public class TestBack extends HttpServlet {
private static final long serialVersionUID =
1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestBack() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(
"get请求");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
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");
}
}
HttpUtil.java
package com.job.utli;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
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;
}
}
MD5Util.java
package com.job.utli;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/***
*md5
* @author niewei
*
*/
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;
}
}
以上代码编写完了之后就跑起来
测试
1.我使用火狐浏览器—》附加组件—》搜索HttpRequester安装重启火狐即可 2.
在测试工具中填写如下类型参数即可,注意回调地址我写的调度中心的测试方法 3.等5s中就能在在控制台中打印出来
以上大致就完成了,查看任务详情,和删除任务就不一一测试了。
以上只是简单得一个场景测试,重启服务器任务就丢失,所以这样不是很推荐这样在生产环境中使用,后边文章中会吧任务放置数据库中。