quartz入门(hello world)简单说明

日志:

Quartz使用SLF4J框架来满足所有的日志记录需求

SchedulerFactory

quartz中SchedulerFactory实现类:
    org.quartz.impl.StdSchedulerFactory
    org.quartz.impl.DirectSchedulerFactory

StdSchedulerFactory:

创建和初始化:
       1.配置(java.util.Properties属性完成->配置文件中加载)
       2.程序创建并直接传递到工厂

DirectSchedulerFactory:

不支持配置完成初始化,程序编辑所有调度程序的设置,要求用户了解全过程(不支持)

Job

quartz中定义job都要实现org.quartz.Job接口,并在execute方法中定义job的执行流程

public class HelloJob implements Job{
    private static Logger logger = LoggerFactory.getLogger(HelloJob.class);
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("hello world!!!");
    }
}
JobDetail

然而我们有时还需获取job相关属性,根据job属性来定义执行流程,此时我们则可以使用JobExecutionContext 对象来获取,如通过getJobDetail()来获取预先定义的job属性

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("hello world!!!");
        JobDetail jobDetail=jobExecutionContext.getJobDetail();
        JobDataMap jobDataMap=jobDetail.getJobDataMap();
        String name=jobDataMap.getString("name");
        String sex=jobDataMap.getString("sex");
        Double height=jobDataMap.getDouble("height");
        //取出自定义对象
        Hero hero=(Hero) jobDataMap.get("hero");
        int age=jobDataMap.getIntValue("age");
        logger.info("name:"+name+"\tsex:"+sex+"\tage:"+age+"\theight:"+height);
        logger.info("hero:");
        logger.info(hero.toString());
    }
JobDataMap

在上面的案例中我们用到了JobDetail中的JobDataMap,下面演示如何利用JobDataMap向jobExecutionContext传递参数

    public static JobDetail defineJobDetailAndTieToRealJobClass(){
        //存入JobDataMap(合并使用)
        JobDataMap newJobDataMap=new JobDataMap();
        newJobDataMap.put("name","关羽");
        newJobDataMap.put("age",89);
        newJobDataMap.put("height",2.8D);

        //通过自己创建JobDataMap存入自定义对象
        Hero hero=new Hero("张飞","男",45,1.89D);
        newJobDataMap.put("hero",hero);

        JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1")
                .usingJobData("name","刘备")
                .usingJobData("age",54)
                .usingJobData("sex","男")
                .usingJobData(newJobDataMap)//putAll合并JobDataMap
                .build();
        return job;
    }

执行结果:

[INFO] 26 五月 06:02:00.010 下午 DefaultQuartzScheduler_Worker-1 [com.feifei.test1.HelloJob]
hello world!!!

[INFO] 26 五月 06:02:00.012 下午 DefaultQuartzScheduler_Worker-1 [com.feifei.test1.HelloJob]
name:关羽 sex:男   age:89  height:2.8

[INFO] 26 五月 06:02:00.012 下午 DefaultQuartzScheduler_Worker-1 [com.feifei.test1.HelloJob]
hero:

[INFO] 26 五月 06:02:00.012 下午 DefaultQuartzScheduler_Worker-1 [com.feifei.test1.HelloJob]
Hero{name='张飞', sex='男', age=45, height=1.89}

自定义对象(考虑序列化问题实现Serializable接口):

public class Hero implements Serializable{
    private String name;
    private String sex;
    private int age;
    private Double height;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

    public Hero() {
    }

    public Hero(String name, String sex, int age, Double height) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

JobDataMap中可以包含不限量的(序列化的)数据对象,JobDataMap是Java Map接口的一个实现,只是额外增加了一些便于存取基本类型的数据的方法来减少存储取出时的强制类型转换。如下:

putAsString(String,boolean):void
getIntValue(String):int
getDoubleValue(String):Double
getFloatValue(String):Float
getLongValue(String):Long

相关的方法还有很多,这里只是列举出一部分。
如果你在JobDataMap中存储的都是java标准类型时并不用担心什么。
如果JobDataMap中存储的有自定义对象,而你又恰好使用持久化的存储机制,那么你就要注意了:
JobDataMap中存储的对象都会被序列化,如果你已经有了一个类序列化后的实例,在那之后有人改变了该类的定义,则有可能因破坏了兼容性而产生异常。
持久化的存储机制(JobStore中说明)
简单解决(如何配置以后说明):
配置JDBC-JobStore和JobDataMap只允许存储基本类型和String类型的数据

经过上面的学习我们已经能够向execute中传递和使用参数了,现在我们再思考一些细节问题:

我们可以通过JobDetail来设置job属性,我们为什么不能直接使用job实现类的属性呢,定义Job实现类时有什么要注意的呢?

scheduler在执行job的execute(…)之前,首先会调用HelloJob的newInstance()创建一个新的实例,调用完成后,HelloJob实例引用就被丢弃了,接着被垃圾回收,可知
    1.HelloJob必须有一个无参的构造函数(当使用默认的JobFactory时);
    2.job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留。(每次执行会重新创建一个HelloJob实例,之前定义的数据都会丢失)

我们已经学会用JobDetail中的JobDataMap来存入和取出数据了,但每次都一个一个的根据key取出,有什么简便方法吗?

使用JobFactory实现数据的自动注入是个不错的选择,他能让你的excute()方法变的更加简洁,只要在HelloJob中添加对应的自定义属性和set方法即可,JobFactory会帮你完成余下的工作的,HelloJob修改如下:

public class HelloJob implements Job{
   private static Logger logger = LoggerFactory.getLogger(HelloJob.class);
   private Hero hero;

   public static Logger getLogger() {
       return logger;
   }

   public static void setLogger(Logger logger) {
       HelloJob.logger = logger;
   }

   public Hero getHero() {
       return hero;
   }

   public void setHero(Hero hero) {
       this.hero = hero;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getSex() {
       return sex;
   }

   public void setSex(String sex) {
       this.sex = sex;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public Double getHeight() {
       return height;
   }

   public void setHeight(Double height) {
       this.height = height;
   }

   private String name;
   private String sex;
   private int age;
   private Double height;

   @Override
   public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       logger.info("hello world!!!");

       logger.info("name:"+name+"\tsex:"+sex+"\tage:"+age+"\theight:"+height);
       logger.info("hero:");
       logger.info(hero.toString());
   }
}
相关注解:

@DisallowConcurrentExecution
   位置:HelloJob类
   作用范围:JobDetail对象
   作用效果:不允许JobDetail对象并发运行
@PersistJobDataAfterExecution
   位置:HelloJob类
   作用范围:JobDetail对象
   作用效果:成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,jobDetail在下一次执行时获取到新的数据.

JobDetail配置更多属性:

Durability:如果一个job是非持久的,当没有活跃的trigger与之关联的时候,会被自动地从scheduler中删除。也就是说,非持久的job的生命期是由trigger的存在与否决定的;
RequestsRecovery:如果一个job是可恢复的,并且在其执行的时候,scheduler发生硬关闭(hard shutdown)(比如运行的进程崩溃了,或者关机了),则当scheduler重新启动的时候,该job会被重新执行。此时,该job的JobExecutionContext.isRecovering() 返回true。

JobExecutionException

细心的朋友应该已经发现了Job.execute()方法上声明了一个运行时异常->
JobExecutionException,Job通过该异常通知scheduler,这个异常携带着很多信息,你也许该花点时间看看JobExecutionException的文档,以便更好的处理此类异常。
下一篇我们开始Trigger,未完待续...

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容