一、什么是Quartz
Quartz 是一个轻量级任务调度框架,只需要做些简单的配置就可以使用;它可以支持持久化的任务存储,即使是任务中断或服务重启后,仍可以继续运行。Quartz既可以做为独立的应用提供服务,也可以和其他应用集成一起使用。
核心概念:
Quartz的类关系图:
注意:Quartz的版本与Spring 的版本有关, Spring 2.x的版本最好用Quartz 1.8.5的,若是 Spring 3.0以上的Quartz 的版本最好用 2.0以上的。
二、基于Sping+Quartz实现简单的JAVA邮件发送
1.创建一个Java(Web)工程
2.实现SimpleMail、MailJob、EmailScheduler类
SimpleMail:
1 package com.quartz.mail; 2 3 import org.apache.commons.mail.EmailException; 4 import org.apache.commons.mail.SimpleEmail; 5 6 import javax.mail.internet.AddressException; 7 import javax.mail.internet.InternetAddress; 8 import java.util.ArrayList; 9 import java.util.Date;10 import java.util.List;11 12 /**13 * Created by xiwu.xxw on 2015/8/8.14 */15 public class SimpleMail {16 private SimpleEmail mail;17 18 /**19 * 初始化一封邮件,暂不支持富媒体和附件20 * @param receivers 邮件的接收者21 * @param subject 邮件主题22 * @param content 邮件内容23 * @throws EmailException24 * @throws AddressException25 */26 public SimpleMail(Listreceivers,String subject,String content) throws EmailException, AddressException {27 mail=new SimpleEmail();28 mail.setCharset("UTF-8");29 List toList=new ArrayList ();30 for(String receiver: receivers){31 toList.add(new InternetAddress(receiver));32 }33 mail.setTo(toList);34 mail.setSubject(subject);35 mail.setContent(content, "text/html;charset=utf-8");36 }37 38 /**39 * 发送邮件40 * @param from 发送方邮件地址41 * @param password 发送授权码42 * @return43 * @throws EmailException44 */45 public String sendEmail(String from,String password) throws EmailException {46 mail.setFrom(from);47 //发送方邮箱权限认证,发送方邮箱须开通SMTP/POP/IMAP功能48 mail.setAuthentication(from, password);49 mail.setHostName("smtp." + from.split("@")[1]);50 mail.setSentDate(new Date());51 return mail.send();52 }53 }
MailJob:
1 package com.quartz.job; 2 3 import com.quartz.mail.SimpleMail; 4 import org.quartz.JobDataMap; 5 import org.quartz.JobExecutionContext; 6 import org.quartz.JobExecutionException; 7 import org.springframework.scheduling.quartz.QuartzJobBean; 8 9 import java.util.List;10 11 /**12 * Created by xiwu.xxw on 2015/8/8.13 */14 public class MailJob extends QuartzJobBean {15 /**16 * 执行Job任务17 * @param context18 * @throws JobExecutionException19 */20 @Override21 protected void executeInternal(JobExecutionContext context) throws JobExecutionException {22 JobDataMap map=context.getJobDetail().getJobDataMap();23 try {24 SimpleMail mail=new SimpleMail((List) map.get("receivers"),map.getString("subject"),map.getString("content"));25 String result=mail.sendEmail(map.getString("from"), map.getString("password"));26 System.out.println(result);27 } catch (Exception e) {28 e.printStackTrace();29 }30 }31 }
EmailScheduler:
1 package com.quartz.scheduler; 2 3 import org.quartz.SchedulerException; 4 import org.quartz.impl.StdScheduler; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 import org.springframework.scheduling.quartz.CronTriggerBean; 7 import org.springframework.scheduling.quartz.JobDetailBean; 8 import org.springframework.scheduling.quartz.SimpleTriggerBean; 9 10 import java.util.ArrayList;11 import java.util.List;12 13 /**14 * Created by xiwu.xxw on 2015/8/8.15 */16 public class EMailScheduler {17 public static void main(String[] args) throws SchedulerException {18 //收件人19 Listreceivers=new ArrayList ();20 receivers.add("xxxxx@qq.com");21 receivers.add("xxxxx@126.com");22 receivers.add("xxxxx@163.com");23 24 ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");25 //邮件JobBean26 JobDetailBean mailJob= (JobDetailBean) context.getBean("mailJob");27 mailJob.setName("mailJob");28 mailJob.setGroup("textEmail");29 // 指明任务就算没有绑定Trigger仍保留在Quartz的JobStore中30 //mailJob.setDurability(true);31 mailJob.getJobDataMap().put("receivers",receivers);32 mailJob.getJobDataMap().put("subject","基于Quartz实现邮件发送");33 mailJob.getJobDataMap().put("content","本程序基于Quartz实现了定时群发邮件的功能,目前只支持文本发送!");34 35 36 //发送邮件任务的SimpleTrigger触发器37 SimpleTriggerBean simpleTrigger= (SimpleTriggerBean) context.getBean("SimpleTrigger");38 39 //发送邮件任务调度器40 StdScheduler scheduler= (StdScheduler) context.getBean("startQuartzTask");41 //加入一个任务到Quartz框架中, 并与simpleTrigger关联42 //Quartz会自动校正与设置simpleTrigger的JobName与JobGroup属性43 scheduler.scheduleJob(mailJob,simpleTrigger);44 45 //发送邮件任务的CronTrigger触发器46 CronTriggerBean croTrigger= (CronTriggerBean) context.getBean("CronTrigger");47 //将发送邮件任务的触发器与邮件任务关联并注册到调度器48 croTrigger.setJobName("mailJob");49 croTrigger.setJobGroup("textEmail");50 //因为任务已在上一条语句中已加入, 所以不能再使用scheduleJob(JobDetail, Trigger)51 scheduler.scheduleJob(croTrigger);52 53 try {54 //开始调度55 scheduler.start();56 } catch (SchedulerException e) {57 e.printStackTrace();58 }59 }60 }
3.配置applicationContext.xml
1 211 12 13 20 2114 1815 1716 19 22 30 3123 28 2932 46 4733 35com.quartz.job.MailJob 3436 44 4548 58 5949 515000 5052 54120000 5355 573 5660 65 6661 630 25/2 17 8 8 ? 2015 6264 67
4.效果如下
三、注意事项
(1)Job被创建后,可以保存在Scheduler中,与Trigger是独立的,同一个Job可以有多个Trigger;这种松耦合的另一个好处是,当与Scheduler中的Job关联的trigger都过期时,可以配置Job稍后被重新调度,而不用重新定义Job;还有,可以修改或者替换Trigger,而不用重新定义与之关联的Job。
(2)将Job和Trigger注册到Scheduler时,可以为它们设置key,配置其身份属性。Job和Trigger的key(JobKey和TriggerKey)可以用于将Job和Trigger放到不同的分组(group)里,然后基于分组进行操作。同一个分组下的Job或Trigger的名称必须唯一,即一个Job或Trigger的key由名称(name)和分组(group)组成。
(3)在Quartz中,如果实现org.quartz.Job接口,那么这个job是stateless的,job实例的参数不能在多个任务之间共享,做并发,如果实现org.quartz.StatefulJob,这个job是个单例的,job实例的属性可以从当前任务传递到下一个任务,做串行。