4

Quartz JobDataMap有以下问题。我希望当使用简单的 Quartz Job并将非原始对象(例如StringBuilder的实例)传递给JobDateMap时,应该始终使用我放置的对象的不同副本来调用方法execute (来自我的工作)。不幸的是,我总是得到放入JobDateMap的对象实例(就像它是 StatefulJob 一样)。

在下面的示例中,我希望在每次调用中都得到一个 '*',而我每次都得到一个 '*'。

public class MyJob implements Job {

    public static void main(String[] args) throws SchedulerException {

        SchedulerFactory schedFact = new StdSchedulerFactory();
        Scheduler sched = schedFact.getScheduler();

        JobDetail jobDetail = new JobDetail("job", Scheduler.DEFAULT_GROUP, MyJob.class);
        jobDetail.getJobDataMap().put("param", new StringBuilder());

        Trigger trigger = TriggerUtils.makeImmediateTrigger("trigger", 10, 100);
        trigger.setGroup(Scheduler.DEFAULT_GROUP);

        sched.scheduleJob(jobDetail, trigger);
        sched.start();

        try {
            Thread.sleep(1000L);
        } catch (Exception e) {}

        sched.shutdown(true);

    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        StringBuilder sb = (StringBuilder) context.getMergedJobDataMap().get("param");
        sb.append("*");
        System.out.println(sb.toString());

    }
}

我想,我错过了关于 Quartz 是如何工作的一些东西。有谁知道什么?

4

5 回答 5

7

Quartz 中还有其他工具可以让您以更优化的方式传递非基元。查看 SchedulerContext 类功能。

using System;
using System.Text;
using Quartz;
using Quartz.Impl;

namespace QuartzNET.Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create RAMJobStore instance
            DirectSchedulerFactory.Instance.CreateVolatileScheduler(1);
            ISchedulerFactory factory = DirectSchedulerFactory.Instance;

            // Get scheduler and add object
            IScheduler scheduler = factory.GetScheduler();
            scheduler.Context.Add("History", new StringBuilder("Runtime History: "));

            // Create job and trigger
            IJobDetail job = JobBuilder.Create<MyJob>()
                                       .WithIdentity("MyJob")
                                       .Build();
            ITrigger trigger = TriggerBuilder.Create()
                                             .WithIdentity("Trigger")
                                             .StartNow()
                                             .WithSimpleSchedule(x => x
                                                .WithInterval(TimeSpan.FromMinutes(1))
                                                .RepeatForever())
                                             .Build();

            // Run it all
            scheduler.Start();
            scheduler.ScheduleJob(job, trigger);
        }
    }

    class MyJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            var history = context.Scheduler.Context["History"] as StringBuilder;
            history.AppendLine(context.NextFireTimeUtc.ToString());
            Console.WriteLine(context.NextFireTimeUtc);
        }
    }
}
于 2014-10-20T18:23:39.807 回答
6

“仅在 JobDataMap 中存储原始数据类型(包括字符串)以避免短期和长期的数据序列化问题。”

来源:http ://www.quartz-scheduler.org/documentation/2.3.1-SNAPSHOT/best-practices.html#jobdatamap-tips

于 2013-02-01T19:07:23.670 回答
5

根据JobDataMap 的最佳实践,我们不应该将复杂的对象放入 JobDataMap 以避免短期或长期问题。(可能存在序列化问题,当然不能通过修改 Complex 对象类来实现 Serializable 来解决。)

解决方法: 将复杂对象作为Json 字符串传递,并在从 JobDataMap 中检索到它们后对其进行反序列化。

例如,

class OrderLine {
        private long orderLineId;
        private Item item;
    }
    class Item {
        private long itemId;
        private String itemName;
   }
//Putting OrderLine object in JobDataMap
    jobDetail.getJobDataMap().put("complexData", new Gson().toJson(new OrderLine()));
// Retrieving data from JobDataMap
    String complexDataString = 
        context.getJobDetail().getJobDataMap().getString("complexData");
    OrderLine orderLine = new Gson().fromJson(complexDataString, OrderLine.class);
于 2017-06-29T18:52:44.547 回答
1

我在我们的项目中遇到了同样的错误,但我意识到我有一个不同的设置阻止了它。如果您配置它,您可以使用非“属性相关”的对象。您正在石英设置的配置文件中查找此值。

<add key="quartz.jobStore.useProperties" value="false" />

False 允许您使用除属性之外的其他对象。一旦我改变了这个(我的是真的),它就开始为我工作了。

于 2017-05-15T17:17:44.903 回答
0

我使用 JSON 将复杂对象发送到作业。它不是很聪明,但适合我的目的。

在您的应用程序中:

jobDetail.getJobDataMap().put("YOUR_PARAM_NAME", yourObject.toJson());

在你的工作中:

JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String jsonObject = dataMap.getString("YOUR_PARAM_NAME");
YourClass yourObject = YourClass.fromJson(jsonObject);
于 2015-04-09T20:01:38.070 回答