elastic-job 分布式定时任务框架 在 SpringBoot 中如何使用(二)动态添加任务需求
之前一篇用过了如何在使用创建最简单的任务:比如每天定时清空系统的缓存
这篇文章主要讲解:如何运用elastic-job-lite做灵活的细粒度任务,比如:
如何定时取消某个订单在下订单后30分钟未支付的订单,并改变订单状态?
如何让某个用户在获得7天体验会员在七天后改变这个会员的会员状态?
某个用户想定时发布一篇文章?
如何给某个会员在生日当天发送一条祝福短信?
elastic-job-lite 就能实现这样的需求……
主要是任务配置,任务执行类都是一样的,下面贴出了demo,仅限于单应用节点时,主要为了实现如何动态的配置任务参数并达到上述需求,方法应用比较简单
首先要有任务(作业)类,并交给spring管理类
/* * Copyright 1999-2015 dangdang.com. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * </p> */ package com.dianji.task_server.job.exec; import com.dangdang.ddframe.job.api.ShardingContext; import com.dangdang.ddframe.job.api.simple.SimpleJob; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.text.MessageFormat; @Slf4j @Component public class OrderExpireJob implements SimpleJob { @Value("${serverFlag}") private String serverFlag; @Override public void execute(final ShardingContext shardingContext) { int shardingItem = shardingContext.getShardingItem(); String jobName = shardingContext.getJobName(); String jobParameter = shardingContext.getJobParameter(); String logRule = "「执行订单超时任务」任务名:{0},订单号:{1},任务分片索引:{2},服务进程「{3}」"; String logStr = MessageFormat.format(logRule, jobName, jobParameter, shardingItem, serverFlag); log.info(logStr); } }
接着就是任务(作业)配置了
package com.dianji.task_server.job.config; import com.dangdang.ddframe.job.api.simple.SimpleJob; import com.dangdang.ddframe.job.config.JobCoreConfiguration; import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration; import com.dangdang.ddframe.job.event.JobEventConfiguration; import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration; import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler; import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter; import com.dianji.task_server.job.exec.OrderExpireJob; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 动态添加任务配置 * * @author szliugx@gmail.com * @create 2018-10-25 下午5:16 **/ @Slf4j @Component public class DynamicAddJobConfig { @Autowired private ZookeeperRegistryCenter regCenter; @Autowired private JobEventConfiguration jobEventConfiguration; public void dynamicAddSimpleJobScheduler(SimpleJob simpleJob, String jobName, String jobParameter, String cron, int shardingTotalCount, String shardingItemParameters) { new SpringJobScheduler( simpleJob, regCenter, getLiteJobConfiguration( jobName, jobParameter, OrderExpireJob.class, cron, shardingTotalCount, shardingItemParameters), jobEventConfiguration).init(); } /** * 任务配置 * * @param jobName * @param jobParameter * @param jobClass * @param cron * @param shardingTotalCount * @param shardingItemParameters * @return */ private LiteJobConfiguration getLiteJobConfiguration( final String jobName, final String jobParameter, final Class<? extends SimpleJob> jobClass, final String cron, final int shardingTotalCount, final String shardingItemParameters) { return LiteJobConfiguration.newBuilder( new SimpleJobConfiguration( JobCoreConfiguration.newBuilder( jobName, cron, shardingTotalCount ).shardingItemParameters(shardingItemParameters).jobParameter(jobParameter).build(), jobClass.getCanonicalName() ) ).overwrite(true).build(); } }
最后,主动触发任务添加,这里用了一个restful API 的URL来请求 测试 「让某个订单1分钟后执行过期作业」 任务添加
package com.dianji.task_server.web.controller; import com.dianji.task_server.job.config.DynamicAddJobConfig; import com.dianji.task_server.job.exec.OrderExpireJob; import com.dianji.task_server.util.ResultUtils; import com.dianji.task_server.web.vo.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 测试控制器 * * @author szliugx@gmail.com * @create 2018-10-17 上午9:46 **/ @RestController @RequestMapping("/test") @Slf4j public class TestController { @Autowired DynamicAddJobConfig dynamicAddJobConfig; @Autowired private OrderExpireJob orderExpireJob; @GetMapping("/addTask") public Result addTask(HttpServletRequest request) { Date date = new Date(); // 当前时间 String orderNo = String.valueOf(date.hashCode()); // 订单号 String jobName = "OrderExpireJob-" + orderNo; // 任务名称(不能重复,不然容易覆盖掉) Date expireTime = addMin(date, 1); // 测试时,1分钟即可 String cron = testGetCron(expireTime); // 得到cron表达式 String jobParameter = orderNo; // 将订单号作为参数 int shardingTotalCount = 1; // 分片总数 String shardingItemParameters = "0=a"; // 分片参数 dynamicAddJobConfig.dynamicAddSimpleJobScheduler(orderExpireJob, jobName, jobParameter, cron, shardingTotalCount, shardingItemParameters); log.info("「添加订单超时任务」,任务名{},订单号{}", jobName, jobParameter); return ResultUtils.success(); } /** * 仅测试使用方法,日期转cron表达式 * * @param date 待处理日期 * @return */ private String testGetCron(java.util.Date date) { String dateFormat = "ss mm HH dd MM ? yyyy"; SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); String formatTimeStr = ""; if (date != null) { formatTimeStr = sdf.format(date); } return formatTimeStr; } /** * 仅测试使用方法,给指定的日期添加分钟 * * @param oldDate 需要处理日期 * @param number 添加的分钟数 * @return */ private Date addMin(Date oldDate, int number) { Calendar c = Calendar.getInstance(); c.setTime(oldDate); c.add(Calendar.MINUTE, number);// 添加分钟 return c.getTime(); } }
应用跑起来后,访问 /test/addTask 查看日志结果:
作业维护后台,能看见执行的这些 订单过期任务