大数跨境
0
0

Spring Boot + JobRunr 后台任务执行神器,太强大了

Spring Boot + JobRunr 后台任务执行神器,太强大了 Spring全家桶实战案例
2025-07-31
0
导读:Spring Boot + JobRunr 后台任务执行神器,太强大了
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!

🎉🎉《Spring Boot实战案例合集》目前已更新151个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

1.1 什么是JobRunr

JobRunr提供了一个统一的编程模型,以可靠的方式处理后台任务,并且可以在共享主机、专用主机或云环境(如Kubernetes)中的JVM实例上运行这些任务。

使用纯Java 8的lambda表达式,就能在Java应用程序中以令人难以置信的简便方式执行“即发即忘”(fire-and-forget)、延迟、定时和重复性任务。它支持CPU密集型、I/O密集型、长时间运行和短时间运行的任务。持久化存储可通过关系型数据库管理系统(RDBMS,如Postgres、MariaDB/MySQL、Oracle、SQL Server、DB2和SQLite)或非关系型数据库(NoSQL,如ElasticSearch、MongoDB和Redis)实现。

1.2 特性

  • 简单:只需使用Java 8的lambda表达式即可创建后台任务

  • 分布式且支持集群:通过乐观锁保证单个调度器实例执行任务

  • 任务持久化:可使用关系型数据库(四张表和一个视图)或非关系型数据库存储

  • 可嵌入:专为嵌入现有应用程序而设计

  • 依赖项极少:(ASM、slf4j以及jackson和jackson-datatype-jsr310、gson或符合JSON-B标准的库中的任意一种)

1.3 使用场景

以下是一些可能非常适合使用JobRunr的场景:

  • 在REST API中,立即向客户端返回响应,并在后台执行长时间运行的任务

  • 批量通知/发送新闻通讯

  • 计算工资并生成相应文件

  • 从xml、csv或json批量导入数据

  • 创建存档

  • 触发Webhook

  • 处理图像/视频

  • 清除临时文件

  • 生成定期自动化报告

  • 数据库维护

  • 数据变更后更新Elasticsearch/Solr

  • ……等等

2.实战案例

2.1 环境准备

引入依赖

<dependency>  <groupId>org.jobrunr</groupId>  <artifactId>jobrunr-spring-boot-3-starter</artifactId>  <version>7.5.3</version></dependency><!-- 如果你使用的Spring Boot2.x 那么请引入jobrunr-spring-boot-2-starter-->

配置

org:  jobrunr:    # 开启任务调度    job-scheduler:      enabled: true    # 启用任务的后台处理    background-job-server:      enabled: true    # 开启dashboard功能    dashboard:      enabled: true      username: pack      password: 123456      port: 7788

如上通过配置文件,你还可以通过代码的方式配置:

@BeanJobScheduler initJobRunr(DataSource dataSource, JobActivator jobActivator) {  return JobRunr.configure()      .useJobActivator(jobActivator)      .useStorageProvider(new InMemoryStorageProvider())      .useBackgroundJobServer()      .useDashboard()      .initialize()      .getJobScheduler();}

默认情况下,你还需要配置 StoreageProvider bean,该接口用来存储后台执行的任务信息。

@BeanStorageProvider storageProvider(JobMapper jobMapper) {  InMemoryStorageProvider storageProvider = new InMemoryStorageProvider();  storageProvider.setJobMapper(jobMapper) ;  return storageProvider ;}

这里配置了基于内存的存储,它默认提供了非常多的实现,你可以根据自己的需要进行配置。

启动服务,访问 http://localhost:7788/dashboard

注意:用户名密码为什么配置文件中配置的,pack/123456。

2.2 手动执行任务

如下示例我们通过 @Job 定义任务,该任务将会在dashboard中展示。

@Servicepublic class TaskService {
  private final Logger logger = LoggerFactory.getLogger(getClass());
  @Job(name = "简单的任务, 没有参数")  public void execute() {    logger.info("这是一个简单的任务, 没有任何参数") ;    try {      TimeUnit.SECONDS.sleep(3) ;    } catch (InterruptedException e) {      e.printStackTrace();    } finally {      logger.info("任务已完成...");    }  }}

接下来,我们需要通过 JobScheduler 执行任务

@RestController@RequestMapping("/task")public class TaskController {  private final JobScheduler jobScheduler;  private final TaskService taskService ;  public TaskController(JobScheduler jobScheduler, TaskService taskService) {    this.jobScheduler = jobScheduler;    this.taskService = taskService;  }
  @GetMapping("/1")  public ResponseEntity<?> task1() {    JobId enqueue = jobScheduler.enqueue(        () -> taskService.execute()) ;    return ResponseEntity.ok(enqueue.toString()) ;  }}

调用该接口后,我们可以从dashboard看到执行完成后的任务

对于该任务,我们还可以指定一个未来的时间执行,如下示例:

@GetMapping("/1")public ResponseEntity<?> task1() {  JobId enqueue = jobScheduler.schedule(LocalDateTime.now().plusSeconds(30), () -> taskService.execute()) ;  return ResponseEntity.ok(enqueue.toString()) ;}

指定任务30s后再执行。

2.3 自动执行任务

我们还可以通过 @Recurring 注解定义周期性的任务,如下示例:

@Servicepublic class TaskService {
  @Recurring(id = "pack-job", cron = "0/15 * * * * *")  @Job(name = "Pack周期性任务")  public void doRecurringJob(JobContext context) {    System.out.println("周期性执行任务...") ;  }}

注意:@Recurring 注解的方法只能包含零个参数,或仅包含一个类型为 org.jobrunr.jobs.context.JobContext 的参数。还有一点要注意,如果你当前的运行环境不是由 IoC 框架(如 Spring、Quarkus 或 Micronaut)管理的 Bean 中的方法,那么该注解不会生效。

上面定义的任务将会每15秒执行一次。如果我们的周期设置的小于15s,那么会每隔15s会执行(15/n次)。

启动服务后,查看dashboard

这种周期任务,我们可以在该界面进行删除或者触发任务的。管理任务是非常的方便。

2.4 任务过滤器&重试

Job 过滤器可用于在作业成功或失败时通过额外的业务流程扩展 JobRunr 的功能。

要创建作业过滤器,只需实现一个具有 JobClientFilter 或 JobServerFilter 接口的 Bean 即可。其他过滤器也可用,如 ApplyStateFilter 和 ElectStateFilter。如下示例,定义任务成功或失败的执行动作。

@Componentpublic class TaskFilter implements JobServerFilter {  @Override  public void onProcessingSucceeded(Job job) {    System.err.printf("%s - 【%s】任务成功执行完成...%n"        Thread.currentThread().getName(), job.getJobName()) ;  }  @Override  public void onProcessingFailed(Job job, Exception e) {    System.err.printf("%s - 【%s】任务执行失败,错误信息: %s%n"        Thread.currentThread().getName(), job.getJobName(), e.getMessage());  }}

接下来,我们为上面的任务配置过滤器

@Recurring(id = "pack-job", cron = "0/15 * * * * *")@Job(name = "Pack周期性任务", jobFilters = {TaskFilter.class})public void doRecurringJob(JobContext context) {  // 这里也可以模拟异常  System.out.println("周期性执行任务...") ;}

通过jobFilters可以配置多个任务过滤器。

运行结果

任务重试

当我们的任务执行失败后,可以通过配置任务重试策略,如下示例:

配置任务重试策略

org:  jobrunr:    jobs:      default-number-of-retries: 3      retry-back-off-time-seed: 1

定义带参数的任务

// 这里通过%0 可以获取第一个方法参数@Job(name = "简单任务,有一个参数 %0")public void execute(String input) {  logger.info("任务开始执行,参数input: {}", input) ;  try {    // 模拟错误    System.err.println(1 / 0) ;  } catch (Exception e) {    logger.error("任务很执行错误", e);    throw new RuntimeException(e) ;  } finally {    logger.info("任务已完成...");  }}

定义Controller

@GetMapping("/2")public ResponseEntity<?> task2(String param) {  JobId enqueue = jobScheduler.enqueue(() -> taskService.execute(param)) ;  return ResponseEntity.ok(enqueue.toString()) ;}

调用任务

最终控制输出

进行了1+3次执行。

控制台查看任务最终状态



以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

在 Spring Boot 中加载属性文件的7种方法

天呐!Java Stream 高效开发!16 个逆天案例,让你秒速起飞!

强大!Spring Boot敏感数据动态配置,这样做更安全

Spring Boot 结合 Redis客户端缓存技术让系统性能飙升

高级开发!一个注解动态控制Controller接口,支持实时更新

绝了!Spring Boot 事务回滚竟藏 5 种神操作

实体与DTO如何转换?这个工具很厉害

处理Null的神器Optional

学会这3招Spring AOP切面技巧,代码解耦效率直接翻倍

性能优化!Spring大事务7条优化建议及示例

如何在Spring Boot中优雅地加载配置?这些方法你必须掌握!

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832