Quartz定时器和发送Email
Posted 阿_毅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz定时器和发送Email相关的知识,希望对你有一定的参考价值。
开心一笑
【从年初的一无所有,到年终的身无分文,唉,我这不忘初心。。。】
新书购买
戳图购买 >>>9.1 使用Quartz定时器
9.1.1 Quartz概述
Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间。Quartz定时器作用很多,比如:定时发送信息、定时生成报表等等。
Quartz框架主要核心组件包括调度器、触发器、作业。调度器作为作业的总指挥,触发器作为作业的操作者,作业为应用的功能模块。其关系如图9-1所示:
图9-1 redis断点调试界面
Job是一个接口,该接口只有一个方法execute,被调度的作业(类)需实现该接口中execute()方法,JobExecutionContext类提供了调度上下文的各种信息。每次执行该Job均重新创建一个Job实例。Job的源码如下所示:
public interface Job
void execute(JobExecutionContext var1) throws JobExecutionException;
Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。JobDetail 用来保存我们作业的详细信息。一个JobDetail可以有多个Trigger,但是一个Trigger只能对应一个JobDetail
Trigger触发器描述触发Job执行规则。主要有SimpleTrigger和 CronTrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等。Cron表达式定义如下:
CronTrigger配置格式:
格式: [秒] [分] [小时] [日] [月] [周] [年]
0 0 12 * * ? 每天12点触发
0 15 10 ? * * 每天10点15分触发
0 15 10 * * ? 每天10点15分触发
0 15 10 * * ? * 每天10点15分触发
0 15 10 * * ? 2005 2005年每天10点15分触发
0 * 14 * * ? 每天下午的 2点到2点59分每分触发
0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ? 每天下午的 18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发
0 10,44 14 ? 3 WED 3月分每周三下午的 2点10分和2点44分触发
0 15 10 ? * MON-FRI 从周一到周五每天上午的10点15分触发
0 15 10 15 * ? 每月15号上午10点15分触发
0 15 10 L * ? 每月最后一天的10点15分触发
0 15 10 ? * 6L 每月最后一周的星期五的10点15分触发
0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发
0 15 10 ? * 6#3 每月的第三周的星期五开始触发
0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次
0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)
Scheduler负责管理Quartz的运行环境,Quartz它是基于多线程架构的,它启动的时候会初始化一套线程,这套线程会用来执行一些预置的作业。Trigger和JobDetail可以注册到Scheduler中。Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。
9.1.2 引入依赖
在Spring Boot中集成Quartz,首先需要在pom.xml文件中引入所需的依赖,具体代码如下:
<!-- quartz定时器 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
9.1.3 定时器配置文件
创建定时器的方法有两种,1)使用XML配置文件的方式。2)使用注解的方式。注解的方式不需要任何配置文件,简单高效,这两种方式都会讲到。我们先来讲第一种方式,也就是配置文件的方式。首先,我们需要在/src/main/resources目录下新建配置文件spring-mvc.xml,具体代码如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<context:annotation-config/>
<!-- 利用import引入定时器的文件 -->
<import resource="spring-quartz.xml"/>
</beans>
< import>标签:利用import标签导入定时器的配置文件,该标签可以根据具体业务分离配置文件。然后,我们在/src/main/resources目录下新建spring-quartz.xml配置文件,具体代码如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 定义Job对象 -->
<bean id="taskJob" class="com.example.demo.quartz.TestTask"/>
<!-- 定义JobDetail对象 -->
<bean id="jobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 目标对象taskJob -->
<property name="targetObject">
<ref bean="taskJob"/>
</property>
<!-- 目标方法 -->
<property name="targetMethod">
<value>run</value>
</property>
</bean>
<!-- 调度触发器 -->
<bean id="myTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 指定使用jobDetail -->
<property name="jobDetail">
<ref bean="jobDetail" />
</property>
<!-- 定义触发规则,每10秒执行一次 -->
<property name="cronExpression">
<value>0/10 * * * * ?</value>
</property>
</bean>
<!-- 调度工厂 -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 注册触发器,可注册多个 -->
<property name="triggers">
<list>
<ref bean="myTrigger"/>
</list>
</property>
</bean>
</beans>
在spring-quartz.xml配置文件中,我们分别定义了Job、JobDetail、Trigger、以及Scheduler。并配置了它们之间的关系。
9.1.4 创建定时器类
定时器的依赖以及配置文件开发完成之后,我们在/src/main/java/com.example.demo.quartz目录下新建定时器类TestTask.java。具体代码如下:
/**
* 描述:定时器类
* @author Ay
* @date 2017/11/18
*/
public class TestTask
//日志对象
private static final Logger logger = LogManager.getLogger(TestTask.class);
public void run()
logger.info("定时器运行了!!!");
如果我们使用第二种创建定时器的方法,相对就简单了,只需要创建一个定时器类,加上相关的注解就搞定了。比如,我们可以在/src/main/java/com.example.demo.quartz目录下创建SendMailQuartz定时器类,具体代码如下:
/**
* 描述:定时器类
* @author Ay
* @date 2017/11/18
*/
@Component
@Configurable
@EnableScheduling
public class SendMailQuartz
//日志对象
private static final Logger logger = LogManager.getLogger(SendMailQuartz.class);
//每5秒执行一次
@Scheduled(cron = "*/5 * * * * * ")
public void reportCurrentByCron()
logger.info("定时器运行了!!!");
@Configurable:加上此注解的类相当于XML配置文件,可以被Spring Boot扫描初始化。
@EnableScheduling:通过在配置类注解@EnableScheduling来开启对计划任务的支持,然后在要执行计划任务的方法上注解@Scheduled,声明这是一个计划任务。
@Scheduled:注解为定时任务,cron表达式里写执行的时机。
9.1.5 Spring Boot扫描配置文件
9.1.3节中,我们已经开发好spring-mvc.xml配置文件,但是想让Spring Boot扫描到该配置文件,还需要在入口类MySpringBootApplication中添加@ImportResource注解,具体代码如下:
@SpringBootApplication
@ServletComponentScan
@ImportResource(locations="classpath:spring-mvc.xml")
public class MySpringBootApplication
//省略代码
@ImportResource:导入资源配置文件,让Spring Boot可以读取到,类似于XML配置文件中的标签。
9.1.6 测试
代码开发完成之后,我们重新启动项目,在Intellij IDEA控制台中可以看到如图9-2所示的信息,证明在Spring Boot中整合Quartz定时器成功。
图9-2 Quartz定时器打印信息
9.2 Spring Boot发送Email
9.2.1 Email介绍
邮件服务在互联网早期就已经出现,如今已成为人们互联网生活中必不可少的一项服务。邮件发送与接收的过程如下:
1)发件人使用SMTP协议传输邮件到邮件服务器A;
2)邮件服务器A根据邮件中指定的接收者,投送邮件至相应的邮件服务器B;
3)收件人使用POP3协议从邮件服务器B接收邮件。
SMTP(Simple Mail Transfer Protocol)是电子邮件(Email)传输的互联网标准,定义在RFC5321,默认使用端口25;
POP3(Post Office Protocol - Version 3)主要用于支持使用客户端远程管理在服务器上的电子邮件。定义在RFC 1939,为POP协议的第三版(最新版)。
这两个协议均属于TCP/IP协议族的应用层协议,运行在TCP层之上。
发送邮件的需求比较常见,如找回密码、事件通知、向用户发送广告邮件等。SUN公司提供给广大Java开发人员的一款邮件发送和接收的开源类库JavaMail,支持常用的邮件协议,如:SMTP、POP3、IMAP等。开发人员使用JavaMail编写邮件程序时,不再需要考虑底层的通讯细节如:Socket,而是关注逻辑层面。JavaMail可以发送各种复杂MIME格式的邮件内容,注意JavaMail仅支持JDK4及以上版本。虽然JavaMail是JDK的API但它并没有直接加入JDK中,所以我们需要另外添加依赖。
Spring提供了非常好用的JavaMailSender接口实现邮件发送。在Spring Boot的Starter模块中已为此提供了自动化配置。
9.2.2 引入依赖
在Spring Boot中集成Mail,首先需要在pom.xml文件中引入所需的依赖,具体代码如下:
<!-- mail start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
9.2.3 添加Email配置
在pom文件引入Mail所需的依赖之后,我们需要在application.properties文件中添加如下的配置信息:
###mail邮件配置
###邮箱主机
spring.mail.host=smtp.163.com
###用户名
spring.mail.username=ay_test@163.com
###设置的授权码
spring.mail.password=ay12345
###默认编码
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
9.2.4 在定时器中发送邮件
在Spring Boot中添加完依赖和配置之后,我们在项目的目录/src/main/java/com.example.demo.mail下新建邮件服务接口类SendJunkMailService,具体代码如下:
/**
* 描述:发送用户邮件服务
* @author Ay
* @date 2017/11/19
*/
public interface SendJunkMailService
boolean sendJunkMail(List<AyUser> ayUser);
然后我们继续在项目的目录/src/main/java/com.example.demo.mail.impl下新建接口类的实现类SendJunkMailServiceImpl.java,具体代码如下:
/**
* 描述:发送用户邮件服务
* @author Ay
* @date 2017/11/19
*/
@Service
public class SendJunkMailServiceImpl implements SendJunkMailService
@Autowired
JavaMailSender mailSender;
@Resource
private AyUserService ayUserService;
@Value("$spring.mail.username")
private String from;
public static final Logger logger =
LogManager.getLogger(SendJunkMailServiceImpl.class);
@Override
public boolean sendJunkMail(List<AyUser> ayUserList)
try
if(ayUserList == null || ayUserList.size() <= 0 ) return Boolean.FALSE;
for(AyUser ayUser: ayUserList)
MimeMessage mimeMessage = this.mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
//邮件发送方
message.setFrom(from);
//邮件主题
message.setSubject("地瓜今日特卖");
//邮件接收方
message.setTo("al_test@163.com");
//邮件内容
message.setText(ayUser.getName() +" ,你知道么?厦门地瓜今日特卖,一斤只要9元");
//发送邮件
this.mailSender.send(mimeMessage);
catch(Exception ex)
logger.error("sendJunkMail error and ayUser=%s", ayUserList, ex);
return Boolean.FALSE;
return Boolean.TRUE;
@Value:可以将application.properties配置文件中的配置设置到属性中。如上面代码中,会将spring.mail.username的值huangwenyi10@163.com设置给from属性。
JavaMailSender:邮件发送接口。在Spring Boot的Starter模块中已为此提供了自动化配置。我们只需要通过注解@Autowired注入进来,即可使用。
在9.1.4节中,我们已经开发了SendMailQuartz定时器类,现在我们重新修改该类,让定时器类能够每隔一段时间,给数据库的用户发送广告邮件,SendMailQuartz类具体的修改如下:
/**
* 描述:定时器类
* @author Ay
* @date 2017/11/18
*/
@Component
@Configurable
@EnableScheduling
public class SendMailQuartz
//日志对象
private static final Logger logger = LogManager.getLogger(SendMailQuartz.class);
@Resource
private SendJunkMailService sendJunkMailService;
@Resource
private AyUserService ayUserService;
//每5秒执行一次
@Scheduled(cron = "*/5 * * * * * ")
public void reportCurrentByCron()
List<AyUser> userList = ayUserService.findAll();
if (userList == null || userList.size() <= 0) return;
//发送邮件
sendJunkMailService.sendJunkMail(userList);
logger.info("定时器运行了!!!");
9.2.5 测试
代码全部开发完成之后,我们重新启动项目,发送邮件定时器类SendMailQuartz每隔5秒(真实项目会设置比较长,比如1天,2天等)会查询数据库表ay_test中的所有用户,并发送广告邮件给对应的用户。我们登陆al_test@163.com邮箱,便可以查看到如图9-1、9-2所示的信息。
图9-1 163邮箱界面 图9-2 163邮件内容
读书感悟
来自《梳毛、八卦及语言的进化》
- 150人的邓巴数字是由人类的大脑决定的,维持 150人的社交 关系,既不会让我们感觉太费劲,又可以最大限度地发挥人多力量大的优势。
- 我们天生喜爱社交,也爱聊八卦,而八卦又反过来推动社会的发展,这样建立 起来的社会是很有人情味的。
- 邓巴数字可以帮助我们估计群体规模,判断何时应该做出调整。而聊八卦更是 我们日常生活的重要组成部分,它既能帮我们维持人际关系,也能创造价值,让 我们作为社会的一份子不觉得寂寞。
经典故事
一天,我发现,一只黑蜘蛛在后院的两檐之间结了一张很大的网。难道蜘蛛会飞?要不,从这个檐头到那个檐头,中间有一丈余宽,第一根线是怎么拉过去的?后来,我发现蜘蛛走了许多弯路。从一个檐头起,打结,顺墙而下,一步一步向前爬,小心翼翼,翘起尾部,不让丝沾到地面的沙石或别的物体上,走过空地,再爬上对面的檐头,高度差不多了,再把丝收紧,以后也是如此。
【蜘蛛不会飞翔,但它能够把网凌结在半空中。它是勤奋、敏感、沉默而坚韧的昆虫,它的网制得精巧而规矩,八卦形地张开,仿佛得到神助。这样的成绩,使人不由想起那些沉默寡言的人和一些深藏不露的智者。于是,我记住了蜘蛛不会飞翔,但它照样把网结在空中。奇迹是执着者造成的。】
大神文章
无
其他
如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎鼓励,点赞、顶、欢迎留下宝贵的意见、多谢支持!
以上是关于Quartz定时器和发送Email的主要内容,如果未能解决你的问题,请参考以下文章