话不多说,直接开干。
1.项目中引入依赖
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
2.配置文件
xxljob:
initenable: true
# xxl-job, access token
accessToken:
cookie: XXL_JOB_LOGIN_IDENTITY=
admin:
addresses: http://192.168.57.***:8546/xxl-job-admin
user:
username: *****
password: *****
executor:
address:
### xxl-job executor address
appname: zhyyk-order-info
ip:
port: 8866
### xxl-job log retention days
logretentiondays: 30
### xxl-job log path
logpath: /Users/Documents/projectLogs
3.配置xxlJob任务参数
package com.xyhsoft.zhyyk.service.job;
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:xxl-job-info.properties")
@ConfigurationProperties(prefix = "xxl-job-info")
@Data
@ToString
public class XxlJobInfoVO {
private String jobGroup;
private String jobDesc;
private String author;
private String scheduleType;
private String glueType;
private String executorHandler;
private String executorRouteStrategy;
private String misfireStrategy;
private String executorBlockStrategy;
private String executorTimeout;
private String executorFailRetryCount;
private String glueRemark;
private String triggerStatus;
}
# \u5B9A\u65F6\u5668\u7EC4
xxl-job-info.jobGroup=1
# \u63CF\u8FF0
xxl-job-info.jobDesc=\u667A\u6167\u533B\u517B\u5EB7\u8BA2\u5355\u5B9A\u65F6\u53D6\u6D88\u652F\u4ED8
# \u521B\u5EFA\u8005
xxl-job-info.author=stx
# \u5B9A\u65F6\u5668\u7C7B\u578B
xxl-job-info.scheduleType=CRON
# glue\u7C7B\u578B
xxl-job-info.glueType=BEAN
# \u6267\u884C\u5668\u4EFB\u52A1handler
xxl-job-info.executorHandler=cancelPay
# \u6267\u884C\u5668\u8DEF\u7531\u7B56\u7565
xxl-job-info.executorRouteStrategy=FIRST
# \u8C03\u5EA6\u8FC7\u671F\u7B56\u7565
xxl-job-info.misfireStrategy=DO_NOTHING
# \u963B\u585E\u5904\u7406\u7B56\u7565
xxl-job-info.executorBlockStrategy=SERIAL_EXECUTION
# \u4EFB\u52A1\u6267\u884C\u8D85\u65F6\u65F6\u95F4\uFF0C\u5355\u4F4D\u79D2
xxl-job-info.executorTimeout=0
# \u5931\u8D25\u91CD\u8BD5\u6B21\u6570
xxl-job-info.executorFailRetryCount=0
# GLUE\u5907\u6CE8
xxl-job-info.glueRemark=GLUE\u4EE3\u7801\u521D\u59CB\u5316
# \u8C03\u5EA6\u72B6\u6001\uFF1A0-\u505C\u6B62\uFF0C1-\u8FD0\u884C
xxl-job-info.triggerStatus=1
4.创建定时任务
根据业务逻辑,上传订单id和自动取消的时间表达式。
Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.add(Calendar.MINUTE, 30); String cron = DateUtils.getDateToCron(cal.getTime()); util.uploadCancelJob(cron, orderId);
上传定时任务相关代码
package com.xyhsoft.zhyyk.service.job;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
@Component
public class CancelPayUtil {
@Value("${xxljob.cookie}")
private String cookie;
@Value("${xxljob.admin.addresses}")
private String xxlJobAdminAddr;
@Autowired
private XxlJobInfoVO xxlJobInfoVO;
public Boolean uploadCancelJob(String cron,String orderId){
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//设置为form方式
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("Cookie", cookie);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("jobGroup", xxlJobInfoVO.getJobGroup());
map.add("jobDesc", xxlJobInfoVO.getJobDesc());
map.add("author", xxlJobInfoVO.getAuthor());
map.add("alarmEmail", "");
map.add("scheduleType", xxlJobInfoVO.getScheduleType());
map.add("scheduleConf", cron);
map.add("cronGen_display", cron);
map.add("schedule_conf_CRON", cron);
map.add("schedule_conf_FIX_RATE", "");
map.add("schedule_conf_FIX_DELAY", "");
map.add("glueType", xxlJobInfoVO.getGlueType());
map.add("executorHandler", xxlJobInfoVO.getExecutorHandler());
map.add("executorParam", orderId);
map.add("executorRouteStrategy", xxlJobInfoVO.getExecutorRouteStrategy());
map.add("childJobId", "");
map.add("misfireStrategy", xxlJobInfoVO.getMisfireStrategy());
map.add("executorBlockStrategy", xxlJobInfoVO.getExecutorBlockStrategy());
map.add("executorTimeout", xxlJobInfoVO.getExecutorTimeout());
map.add("executorFailRetryCount", xxlJobInfoVO.getExecutorFailRetryCount());
map.add("glueRemark", xxlJobInfoVO.getGlueRemark());
map.add("glueSource", "");
map.add("triggerStatus",xxlJobInfoVO.getTriggerStatus());
HttpEntity<MultiValueMap<String, String>> requestb = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(xxlJobAdminAddr+"/jobinfo/add", requestb, String.class);
String regionString = response.getBody();//获取请求体
JSONObject jsonObject = JSONObject.parseObject(regionString);//将请求体转化为json格式
String code = jsonObject.getString("code");
if (!("200".equals(code))) {
throw new IllegalArgumentException("xxl-job定时任务创建失败");
}
return true;
}
5.时间到期执行取消逻辑
订单状态枚举
package com.xyhsoft.zhyyk.service.job;
public enum OrderStatusEnum {
//100=待支付
TO_BE_PAID(100, "待支付"),
//200=已过期
EXPIRED(200, "已过期"),
//300=已支付
PAID(300, "已支付");
//订单状态
private final int status;
//状态描述
private final String description;
OrderStatusEnum(int status, String description)
{
this.status = status;
this.description = description;
}
public int getStatus()
{
return status;
}
public String getDescription()
{
return description;
}
}
订单取消逻辑
/**
* @Descript: 订单超时处理类
* @Author: stx
* @Date: 12/23/22 2:34 PM
*/
@Slf4j
@Component
public class OrderTimeOutJob {
@Autowired
private OrderMapper orderMapper;
@XxlJob("cancelPay")
public void job() {
log.info(">>>>>>>>进入xxl-job定时任务执行方法");
String orderId = XxlJobHelper.getJobParam();
orderMapper.update(entity:null Wrappers.< ~ > lambdaUpdate(
.eg(Order::getId, orderId)
//待支付状态
.eq(Order::getStatus, OrderStatusEnum.TO_BE_PAID.getStatus())
//设置成已过期
.set(Order::getStatus,OrderStatusEnum.EXPIRED.getStatus())
//设置过期时间
set(Order::getExpireDateTime, LocalDateTime.now(Zoneoffset.ofHours(8)))
}
}
到这就结束了,建议收藏,我只是建议哈。
总结:
使用xxljob实现超时订单自动取消可能存在以下一些缺点:
-
依赖于定时任务:xxljob是一个分布式任务调度平台,需要在服务器上部署并配置定时任务。这意味着你需要额外的服务器资源和维护工作来支持这个功能。如果你的应用程序规模较小或者没有专门的服务器管理团队,这可能会增加一些负担。
-
实时性较差:xxljob是基于定时任务的调度系统,它依赖于任务的调度周期。如果你设置的调度周期比较长,例如每隔5分钟检查一次订单超时情况,那么订单的取消可能会有一定的延迟。这对于某些业务场景可能不够实时。
-
扩展性限制:xxljob本身是一个任务调度平台,它的主要功能是执行定时任务。如果你的业务需求变得更加复杂,例如需要根据不同的条件来判断订单是否超时,或者需要与其他系统进行交互来取消订单,那么xxljob可能无法满足这些需求。你可能需要额外的定制开发来扩展xxljob的功能。
-
单点故障风险:如果你只有一个xxljob的实例在运行,那么它成为了单点故障的风险。如果这个实例出现故障或者停机,订单取消功能将无法正常工作。为了提高可用性,你需要考虑部署多个xxljob实例以及相应的负载均衡和故障转移机制。
-
任务调度管理复杂:xxljob虽然提供了任务调度的功能,但是它需要你自己管理任务的状态、调度规则和执行结果等。这可能需要你编写和维护一些额外的代码来管理这些任务。对于一些简单的任务来说,这可能没有太大的问题,但是如果任务规模较大或者复杂度较高,可能需要投入更多的开发和维护工作。
总之,尽管xxljob可以用来实现超时订单自动取消功能,但它也存在一些缺点和局限性。在选择使用xxljob之前,你需要仔细评估你的业务需求,并权衡xxljob的优点和缺点,以确定它是否适合你的应用场景。