当前位置: 首页 > 工具软件 > wed-job > 使用案例 >

动态创建xxl-job任务

梁浩
2023-12-01

1.需求背景:微信小程序秒杀模块有个订阅功能,当用户点击完订阅后,要在活动开始的前10分钟调用微信接口发送订阅消息给用户
2.思路:本地创建秒杀订阅表,当用户添加或者取消时对应表中数据的增删,添加数据时动态创建一条xxljob的定时任务,取消时删除它
xxl-job有两种创建任务的方式,第一种就是我们使用xxl-job的图形化页面,第二种直接调用xxl-job的接口(其实图形化页面也是使用了调用接口的方式)

废话少说,下面是工具类和示例代码以供参考

@Component
public class XxlJobUtil {
    public static final int SUCCESS_CODE = 200;
    private static String adminAddresses;
    private static String appname;
    private static Integer groupId;
    private static String accessToken;

    @Value("${xxl.job.admin.addresses}")
    public void setAdminAddresses(String adminAddresses) {
        XxlJobUtil.adminAddresses = adminAddresses;
    }

    @Value("${xxl.job.accessToken}")
    public void setAccessToken(String accessToken) {
        XxlJobUtil.accessToken = accessToken;
    }

    @Value("${xxl.job.executor.appname}")
    public void setAppname(String appname) {
        XxlJobUtil.appname = appname;
    }

    @PostConstruct
    public void init() {
        initGroupId();
    }

    private static final String ADD_URL = "/ext/jobinfo/add";
    private static final String UPDATE_URL = "/ext/jobinfo/update";
    private static final String REMOVE_URL = "/ext/jobinfo/remove";
    private static final String PAUSE_URL = "/ext/jobinfo/stop";
    private static final String START_URL = "/ext/jobinfo/start";
    private static final String ADD_AND_START_URL = "/ext/jobinfo/add-and-start";
    private static final String GET_GROUP_ID = "/ext/jobgroup/get-group-id";


    /**
     * 添加任务
     * @param jobInfo 任务信息
     * @return {@link String} 任务id
     * @author kritofgo
     * @date 2022/05/27 17:37
     **/
    public static String add(XxlJobInfo jobInfo) {
        jobInfo.setJobGroup(groupId);
        return doPost(adminAddresses + ADD_URL, jobInfo, String.class);
    }

    /**
     * 初始化获取执行器id
     * @author kritofgo
     * @date 2022/05/27 17:37
     **/
    public static void initGroupId() {
        // 查询对应groupId:
        Map<String, Object> param = new HashMap<>(4);
        param.put("appname", appname);
        Integer groupId = doPost(adminAddresses + GET_GROUP_ID, param, Integer.class);
        if (groupId == null) {
            throw new XllJobRemoteException(String.format("【xxl-job】接口调用未获取到分组id,appname:%s", appname));
        }
        XxlJobUtil.groupId = groupId;
    }

    /**
     * 修改执行时间
     * @param id 任务id
     * @param cron cron表达式
     * @return {@link String}
     * @author kritofgo
     * @date 2022/05/27 17:38
     **/
    public static String update(int id, String cron) {
        Map<String, Object> param = new HashMap<>(4);
        param.put("id", id);
        param.put("jobCron", cron);
        return doPost(adminAddresses + UPDATE_URL, param, String.class);
    }

    /**
     * 删除任务
     * @param id 任务id
     * @return {@link String}
     * @author kritofgo
     * @date 2022/05/27 17:39
     **/
    public static String remove(int id) {
        Map<String, Object> param = new HashMap<>(4);
        param.put("id", id);
        return doPost(adminAddresses + REMOVE_URL, param, String.class);
    }

    /**
     * 暂停任务
     * @param id 任务id
     * @return {@link String}
     * @author kritofgo
     * @date 2022/05/27 17:40
     **/
    public static String pause(int id) {
        Map<String, Object> param = new HashMap<>(4);
        param.put("id", id);
        return doPost(adminAddresses + PAUSE_URL, param, String.class);
    }

    /**
     * 开始任务
     * @param id 任务id
     * @return {@link String}
     * @author kritofgo
     * @date 2022/05/27 17:40
     **/
    public static String start(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        return doPost(adminAddresses + START_URL, param, String.class);
    }

    /**
     * 添加并启动
     * @param jobInfo 任务信息
     * @return {@link String}
     * @author kritofgo
     * @date 2022/05/27 20:10
     **/
    public static String addAndStart(XxlJobInfo jobInfo) {
        jobInfo.setJobGroup(groupId);
        return doPost(adminAddresses + ADD_AND_START_URL, jobInfo, String.class);
    }

    @SuppressWarnings("unchecked")
    public static <T> T doPost(String url, Object json, Class<T> clazz) {
        ReturnT<T> returnT = XxlJobRemotingUtil.postBody(url, accessToken, 3, json, clazz);
        if (returnT.getCode() != SUCCESS_CODE) {
            throw new XllJobRemoteException(String.format("【xxl-job】接口调用失败,错误码:%s,原因:%s",
                    returnT.getCode(), returnT.getMsg()));
        }
        return returnT.getContent();
    }

}

cron生成器的工具类

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * @description:
 * @author kritofgo
 * @date 2022/8/10 14:08
 */
public class CronUtil {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ? yyyy");

    /**
     * 年 (可选) 留空
     * 允许的特殊字符:留空, 1970-2099 , - * /
     */
    private String year;
    /**
     * 星期 可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
     * 允许的特殊字符:1-7 或者 SUN-SAT , - * ? / L C #
     */
    private String week;
    /**
     * 月  可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * 允许的特殊字符:1-12 或者 JAN-DEC , - * /
     */
    private String month;
    /**
     * 日 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * 允许的特殊字符:1-31 , - * ? / L W C
     */
    private String day;
    /**
     * 时 可以用数字0-23表示
     * 允许的特殊字符:0-23, - * /
     */
    private String hour;
    /**
     * 分 可以用数字0-59 表示
     * 允许的特殊字符:0-59,- * /
     */
    private String minutes;
    /**
     * 秒 可以用数字0-59 表示
     * 允许的特殊字符:0-59,- * /
     */
    private String seconds ;

    /***
     *  日期转换cron表达式 例如 "0 07 10 15 1 ? 2016"
     * @param date 时间点
     * @return
     */
    public static String getCron(Date date) {
        String formatTimeStr = null;
        if (Objects.nonNull(date)) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }

    /**
     * 获取指定日期的cron表达式
     * @param year 年
     * @param week 星期 可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
     * @param month 月 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 可以用数字0-23表示
     * @param minutes 分 可以用数字0-59 表示
     * @param seconds 秒 可以用数字0-59 表示
     * @return
     */
    public static String getCron(String year,String week,String month,String day,String hour,String minutes,String seconds) {
        return seconds+" "+minutes+" "+hour+" "+day+" "+month+" "+week+" "+year;
    }

    /**
     * 获取指定日期的cron表达式
     * @param week 星期 可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
     * @param month 月 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 可以用数字0-23表示
     * @param minutes 分 可以用数字0-59 表示
     * @param seconds 秒 可以用数字0-59 表示
     * @return
     */
    public static String getCron(String week,String month,String day,String hour,String minutes,String seconds) {
        return getCron("*",week,month,day,hour,minutes,seconds);
    }

    /**
     * 获取指定日期的cron表达式
     * @param month 月 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 可以用数字0-23表示
     * @param minutes 分 可以用数字0-59 表示
     * @param seconds 秒 可以用数字0-59 表示
     * @return
     */
    static String getCron(String month,String day,String hour,String minutes,String seconds) {
        return getCron("?",month,day,hour,minutes,seconds);
    }

    /**
     * 获取指定范围的Cron表达式 例如 13-14 30-31 11-12 20-21 04-05 1-2 2021-2022
     * @param year 年 使用(year1-year2) year1<=year2
     * @param week 星期 使用(week1-week2) 可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
     * @param month 月 使用(month1-month2) 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日  使用(day1-day2) 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 使用(hour1-hour2) 可以用数字0-23表示
     * @param minutes 分  使用(minutes1-minutes2) 可以用数字0-59 表示
     * @param seconds 秒  使用(seconds1-seconds2) 可以用数字0-59 表示
     * @return
     */
    public static String getCronByRange(String year,String week,String month,String day,String hour,String minutes,String seconds) {
        return seconds+" "+minutes+" "+hour+" "+day+" "+month+" "+week+" "+year;
    }

    /**
     * 获取指定范围的Cron表达式 例如 13-14 30-31 11-12 20-21 04-05 1-2
     * @param week 星期 使用(week1-week2) 可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
     * @param month 月 使用(month1-month2) 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日  使用(day1-day2) 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 使用(hour1-hour2) 可以用数字0-23表示
     * @param minutes 分  使用(minutes1-minutes2) 可以用数字0-59 表示
     * @param seconds 秒  使用(seconds1-seconds2) 可以用数字0-59 表示
     * @return
     */
    public static String getCronByRange(String week,String month,String day,String hour,String minutes,String seconds) {
        return getCron("*",week,month,day,hour,minutes,seconds);
    }

    /**
     * 获取指定范围的Cron表达式  例如 13-14 30-31 11-12 20-21 04-05
     * @param month 月 使用(month1-month2) 可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
     * @param day 日  使用(day1-day2) 可以用数字1-31 中的任一一个值,但要注意一些特别的月份
     * @param hour 时 使用(hour1-hour2) 可以用数字0-23表示
     * @param minutes 分  使用(minutes1-minutes2) 可以用数字0-59 表示
     * @param seconds 秒  使用(seconds1-seconds2) 可以用数字0-59 表示
     * @return
     */
    static String getCronByRange(String month,String day,String hour,String minutes,String seconds) {
        return getCron("?",month,day,hour,minutes,seconds);
    }
}

下面是项目中用到的代码示例:

...
 //执行器cron表达式
        String cron = CronUtil.getCron(wxSubscription.getReminderTime());
        log.info("当前cron表达式:----" + cron);
        //执行器任务参数,
        String mId = String.valueOf(wxSubscription.getId());
        //执行器,任务Handler名称
        String handler = "";
        String jobDesc = "秒杀活动订阅消息:" + wxSubscription.getId();
        XxlJobInfo jobInfo = new XxlJobInfo(jobDesc, "admin", handler, mId);
        jobInfo.setSchedule(ScheduleTypeEnum.CRON, cron);
        //创建定时任务提醒用户
        XxlJobUtil.addAndStart(jobInfo);
...
 类似资料: