SuperAPI AI Directory

xxl-job-patterns

Coding & development

View repository

Updated 10-16 05:47

About this skill

XXL-JOB best practice pattern

Source:https://github.com/xuxueli/xxl-job
Based on hiwepy/xxljob-spring-boot-starter(Spring Boot Starter encapsulation)

Capability Boundaries

✅ Strong Suits

  1. @XxlJobCron annotation — 100% replacement for @XxlJob, code as configuration (cron/desc/author/selfStarting all in code)
  2. Automatic registration at startup — when selfStarting=true, the executor automatically registers the task to Admin at startup (no need to manually create it in the UI)
  3. XxlJobTemplate — programmatic task management (add/update/delete/start/stop/trigger), session auto-renewal
  4. v2/v3 dual-version compatibility — Admin version parameter differences (v3 uses ids[], v2 uses id), automatically adapted
  5. Micrometer metrics — automatically collects task execution count/success/failure/duration, integrates with Prometheus
  6. Unirest HTTP client — automatically configures SSL (trust-all)/Cookie management/timeout

❌ Out of Scope

  1. Simple single-machine scheduled tasks → @Scheduled
  2. Alternatives: PowerJob (more powerful), ElasticJob (decentralized)

Core patterns

Pattern 1: @XxlJobCron — code as configuration (recommended)

@Slf4j
@Component
@RequiredArgsConstructor
public class CompensationJobHandler {
    private final AigcTaskCompensationScheduler compensationScheduler;

    // ✅ 一行注解 = @XxlJob + cron + desc + author + selfStarting(自动注册到Admin)
    @XxlJobCron(value = "compensateStaleTextTasks",
                cron = "0/30 * * * * ?",
                desc = "文本回调超时补偿",
                author = "wandl",
                selfStarting = true,   // ← 启动时自动注册,无需在Admin UI手动创建
                failRetryCount = 3,
                timeout = 30)  // 30秒超时
    public void compensateStaleTextTasks() {
        try {
            compensationScheduler.compensateStaleTextTasks();
            XxlJobHelper.handleSuccess("compensation completed");
        } catch (Exception e) {
            log.error("XXL-Job failed", e);
            XxlJobHelper.handleFail("failed: " + e.getMessage());
        }
    }
}

Pattern 2: XxlJobTemplate — programmatic task management

@Service
public class JobManager {
    @Autowired XxlJobTemplate xxlJobTemplate;

    // 创建/更新任务(幂等)
    public void ensureJobRegistered(Long jobGroupId, String handlerName, String cron, String desc) {
        XxlJobInfo jobInfo = new XxlJobInfo();
        jobInfo.setJobGroup(jobGroupId.intValue());
        jobInfo.setExecutorHandler(handlerName);
        jobInfo.setScheduleConf(cron);
        jobInfo.setJobDesc(desc);
        jobInfo.setScheduleType("CRON");
        jobInfo.setGlueType("BEAN");
        jobInfo.setAuthor("system");
        jobInfo.setExecutorRouteStrategy("LEAST_FREQUENTLY_USED");
        jobInfo.setMisfireStrategy("DO_NOTHING");
        jobInfo.setExecutorBlockStrategy("COVER_EARLY");
        jobInfo.setExecutorTimeout(30);
        jobInfo.setExecutorFailRetryCount(3);
        xxlJobTemplate.addUniqueJob(jobInfo);  // 幂等:描述相同不重复创建
    }

    // 手动触发
    public void triggerJob(Integer jobId, String param) {
        xxlJobTemplate.triggerJob(jobId, param);
    }

    // 暂停/恢复
    public void pauseJob(Integer jobId) { xxlJobTemplate.stopJob(jobId); }
    public void resumeJob(Integer jobId) { xxlJobTemplate.startJob(jobId); }
}

Pattern 3: Configuration structure

xxl:
  job:
    accessToken: xxx                      # 通信Token
    admin:
      version: V3_X                       # Admin版本(V2_X / V3_X)
      addresses: http://xxx:9991/xxl-job-admin
      username: admin
      password: xxxxx                     # Admin登录密码
      cookie:                             # Session管理
        maximum-size: 1000
        expire-after-write: 5s
    executor:
      enabled: true
      appname: agent-job-executor         # 执行器名称(与Admin注册一致)
      title: 智能体 - 任务执行器            # 执行器显示名称
      ip: 172.16.0.152                    # 执行器IP(多网卡时指定)
      port: 0                             # 0=自动探测,-1=不启动
      log-path: /logs/xxl-job/jobhandler
      log-retention-days: 30

Pattern 4: SLF4J + RequiredArgsConstructor dependency injection

// ✅ DDD4J 风格:Lombok + 构造器注入
@Slf4j
@Component
@RequiredArgsConstructor  // final字段自动构造器注入
public class MyJobHandler {
    private final OrderService orderService;        // 构造器注入
    private final NotificationService notifyService;

    @XxlJobCron(value = "closeExpiredOrders", cron = "0 0 2 * * ?",
                desc = "关闭过期订单", author = "system", selfStarting = true)
    public void execute() { ... }
}

Pattern 5: Unified error handling pattern

@XxlJobCron(...)
public void execute() {
    try {
        // 业务逻辑
        doWork();
        XxlJobHelper.handleSuccess("处理完成");  // ← 显式标记成功
    } catch (Exception e) {
        log.error("XXL-Job {} failed", getJobName(), e);
        XxlJobHelper.handleFail("失败: " + e.getMessage());  // ← 显式标记失败
    }
}

Gotchas

  1. @XxlJobCron(selfStarting=true) automatic registration — automatically syncs to Admin at startup, no need to manually create it in the UI
  2. Admin version parameter differences — v2 usesid, v3 usesids[], the Starter adapts automatically
  3. Executor port set to 0 for automatic detection — avoids port conflicts, -1 means the executor does not start
  4. Specify ip for multiple network cards — must be specified for multiple network cards in cloud environmentsxxl.job.executor.ip
  5. Session auto-renewal — XxlJobTemplate automatically re-logs in when it detects session expiration
  6. XxlJobHelper.handleFail explicit marking — not calling it is treated as success by default
  7. @RequiredArgsConstructor injection — use final fields + constructor injection, not @Autowired field injection
  8. @XxlJobCron conflicts with MetricMethodJobHandler — XXL-JOB's built-in MetricMethodJobHandler reads @XxlJob.value()through reflection, but @XxlJobCron does not contain the native @XxlJob annotation, resulting in NullPointerException: Cannot invoke "com.xxl.job.core.handler.annotation.XxlJob.value()" because "job" is null. Solutions: ① Disable Micrometer metrics (xxl.job.metrics.enabled=false) ② Also add an empty @XxlJob annotation on the method to solve the reflection problem ③ Upgrade the hiwepy starter version to see whether it has been fixed

Data Privacy

This skill does not collect, store, or transmit any user data.