在Spring中访问计划任务

问题描述 投票:0回答:4

我在 Spring 的任务调度程序中安排了几个任务

<task:scheduled-tasks>
    <task:scheduled ref="task1" method="run"
        cron="0 0 */0 * * *" />
    <task:scheduled ref="task2" method="run"
        cron="0 0 */30 * * *" />
</task:scheduled-tasks>

<task:scheduler id="scheduler" pool-size="10" />

如何从应用程序上下文中访问计划任务列表并检索元信息(例如下一个执行时间)?

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler)context.getBean("scheduler");
//... how to continue from here?
java spring scheduled-tasks
4个回答
5
投票

Spring 中没有公共 API 可以执行此操作。

相关:


5
投票

我刚刚想明白了

从这里开始获取安排的内容。

    ThreadPoolTaskScheduler xScheduler = (ThreadPoolTaskScheduler)this.taskScheduler;

    ScheduledThreadPoolExecutor xService = (ScheduledThreadPoolExecutor)xScheduler.getScheduledExecutor();

    BlockingQueue<Runnable> queue = xService.getQueue();
    Object[] scheduledJobs = queue.toArray();

如果这个数组在调试器中查看实例以找到您需要的内容。

然后编写这样的反射代码来获取 Spring 和 Java 中隐藏的 API。请参阅“可访问”设置,这是获取这些私人物品的唯一方法。您可能需要使用不同的公共类来获取某些私有字段,查看 api 文档并在 Eclipse 中查看这些类的源代码。

            Method delayM = obj.getClass().getDeclaredMethod("getDelay", TimeUnit.class);
            delayM.setAccessible(true);
            // delayM = obj.getClass().getDeclaredMethod("getDelay", TimeUnit.class);
            Long delay = (Long)delayM.invoke(obj, new Object[] { tu } );

触发器和根runnable位于该对象的callable字段中,ReschedulingRunnable的实例不是公共类,询问Spring为什么这样做。您可以通过反射从 DelegatingErrorHandlingRunnable 中获取委托。


0
投票

@Randy Poznan 的答案已经相当不错,但它使用了不必要的反射,并且

delayM.setAccessible(true)
可能会导致 Java 17 出现问题,而且它的访问规则更严格(运行时异常!)。

没有反射的解决方案是这样的:

// Bean is named "taskScheduler" now
ThreadPoolTaskScheduler taskScheduler = (ThreadPoolTaskScheduler) context.getBean("taskScheduler");
ScheduledThreadPoolExecutor scheduledExecutor =
    (ScheduledThreadPoolExecutor) taskScheduler.getScheduledExecutor();

BlockingQueue<Runnable> queue = scheduledExecutor.getQueue();
if (queue.isEmpty()) {
    return null;
} else {
    for (Runnable runnable : queue) {
        // This is it: Casting to `ScheduledFuture`.
        var scheduledFuture = (ScheduledFuture) runnable;
        final long delay = scheduledFuture.getDelay(TimeUnit.MINUTES);

        System.out.println("Delay: " + delay + " on runnable: " + runnable);
    }
}

0
投票

如果您在项目中使用 Spring Boot 执行器,将会有一个端点 (

/actuator/scheduledtasks
) 执行此操作。

您还可以使用负责该端点的代码来访问它。如果您查看源代码并看到这些类是

public
,那么如果您依赖于 spring-boot-actuator(具有
compile
-范围),则可以使用它们:

ScheduledTasksDescriptor scheduledTasks = endpoint.scheduledTasks();
for(TaskDescriptor taskDescriptor : scheduledTasks.getCron()){//iterate through all cron tasks here
    RunnableDescriptor rDescriptor = taskDescriptor.getRunnable();
    String target = rDescriptor.getTarget();
}

但是,这不允许您实际运行任务,而只是为了获取有关它们的信息。

© www.soinside.com 2019 - 2024. All rights reserved.