根据生日定时发送生日祝福邮件

tech2025-01-28  18

需求

根据不同的生日日期,在生日当天发送一个祝福邮件,这是需要做到两个事情

定时,根据生日定时到每年的那一天发送邮件

定时发送

要想做到定时发送,这时就需要一个定时任务调度的工具,这里使用的是Quartz Quartz是一个定时任务调度框架,主要包含三个部分,Schedule(调度器)、 JobDetail(任务)CronTrigger(触发器)

Scheduler 调度器主要是调度调度规则,在规则下启动任务 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); CronTrigger 触发器中可以设置任务的触发规则 主要属性: startNow():设置起始时间为即时启动 **withSchedule:**设置任务的执行规律和执行次数 withIntervalInSecos() :每隔多长时间执行,时间单位是秒 repeatForever():持续循环执行,直到结束 endAt: 触发器的结束时间 因为使用的是CronTrigger,所以时间表达式按照cron的规则 依次为(秒 分 时 日 月 星期 (年(可选))) 特殊符号: **,**并列 - 区间,范围 / 间隔,从起始点间隔多长时间 ***** 任意值 **?**不确定值SimpleTrigger trigger = TriggerBuilder.newTrigger() trigger.startNow(); trigger.withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1) //每秒执行一次 .repeatForever()); trigger.endAt(new Date(120,8,3,12,45,0)) JobDetial 创建新任务要实现Job接口,重写execute方法 public class Myjob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // System.out.println("执行方法"); } } 最后要将任务和触发器交给调度器调度 Trigger trigger = triggerBuilder.build(); //将任务交给触发器 JobDetail job =JobBuilder.newJob(Myjob.class).build(); //将触发器交给调度器 scheduler.scheduleJob(job,trigger); //启动调度器 scheduler.start();

配置式

调度器:ScheduleFacrotyBean 任务:JobDetailFactoryBean 触发器:CronTriggerFactoryBean

<!--配置任务--> <bean name="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="name" value="myjob"/> <property name="group" value="mygroup"/> <property name="jobClass" value="quartz.MyJob3"/> </bean> <!--配置调度规则--> <bean name="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail"/> <property name="cronExpression" value="* * * * * ?"/> </bean> <!--配置调度器--> <bean name="" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger"></ref> </list> </property> </bean>

注解式

要使用注解,首先要扫描目标文件,获取注解解析器

<context:component-scan base-package="quartz"/> <task:annotation-driven/>

使用@Schedule注解

发送邮件

导入相关的jar包: 想要发送邮件,首先要有一个邮件平台 比如腾讯、新浪,并且要开启邮箱的授权码,获得授权码之后才能进行自动转发

public static void sendMessage() throws MessagingException { //设置邮箱服务器类型 String host = "smtp.qq.com"; //设置第三方登录使用验证码 String auth = "xxxxxxxxx"; //设置发件人 Stirng form="xxxxx@qq.com"; //设置收件人 String to="xxxxxx@qq.com"; //获取本地系统参数 Properties properties=System.getProperties(); //设置邮件服务器地址 properties.setProperty("mail.smtp.host",host); //告诉邮件客户端,本次请求是需要认证的 properties.put("mail.smtp.auth", "true"); //获取邮件服务器连接 Session session=Session.getDefaultInstance(properties, new Authenticator() { @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(from,auth); } }); //组装邮件内容 MimeMessage message = new MimeMessage(session); //发送人 message.setFrom(new InternetAddress(from)); //接收人 message.addRecipient(MimeMessage.RecipientType.TO,new InternetAddress(to)); //邮件主题 message.setSubject(subject); //邮件内容 message.setText(context); //发送邮件 Transport.send(message); System.out.println("发送成功"); }

实现

分别实现了定时任务调度和自动转发邮件之后,就可以将自动转发当做一个Job,通过CronTrigger的表达式设置生日,进行定时转发 这里采用配置式,方便对任务的分组和批量管理

将自动发送邮件作为任务

public class MyJob3 implements Job{ @Autowired private UserDao userDao; @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { Calendar calendar=Calendar.getInstance(); int birth_year=calendar.get(Calendar.YEAR); int birth_month=calendar.get(Calendar.MONTH)+1; int birth_day=calendar.get(Calendar.DAY_OF_MONTH); User u=new User(); u.setBirth_year(birth_year); u.setBirth_month(birth_month); u.setBirth_day(birth_day); List<User> users = userDao.selectUserByBirthday(u); for (User user : users) { String from ="xxxxxxxx@qq.com"; String to=user.getEmail(); String subject="生日祝福"; String context="今天是您"+(birth_year-user.getBirth_year()+1)+"的生日,祝你生日快乐"; try { SendMessage.sendMessage(from,to,subject,context); } catch (MessagingException e) { e.printStackTrace(); } } } } //调用SendMessage方法 public class SendMessage{ public static void sendMessage(String from,String to,String subject,String context) throws MessagingException { //设置邮箱服务器类型 String host = "smtp.qq.com"; //设置第三方登录使用验证码 String auth = "xxxxxxxxxxx"; //获取本地系统参数 Properties properties=System.getProperties(); //设置邮件服务器地址 properties.setProperty("mail.smtp.host",host); //告诉邮件客户端,本次请求是需要认证的 properties.put("mail.smtp.auth", "true"); //获取邮件服务器连接 Session session=Session.getDefaultInstance(properties, new Authenticator() { @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(from,auth); } }); //组装邮件内容 MimeMessage message = new MimeMessage(session); //发送人 message.setFrom(new InternetAddress(from)); //接收人 message.addRecipient(MimeMessage.RecipientType.TO,new InternetAddress(to)); //邮件主题 message.setSubject(subject); //邮件内容 message.setText(context); //发送邮件 Transport.send(message); System.out.println("发送成功"); } }

配置文件

因为生日是从数据库中读取的,使用到了ssm框架进行整合 在spring配置文件中配置定时任务调度

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 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.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--配置任务--> <bean name="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="name" value="myjob"/> <property name="group" value="mygroup"/> <property name="jobClass" value="quartz.MyJob3"/> </bean> <!--配置调度规则--> <bean name="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail"/> <property name="cronExpression" value="0 0 6 * * ?"/> </bean> <!--配置调度器--> <bean name="" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger"></ref> </list> </property> </bean> <!-- 配置数据库配置文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="${url}"/> <property name="username" value="${jdbc.userName}"/> <property name="password" value="${password}"/> </bean> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath*:Dao/*.xml"/> </bean> <mybatis:scan base-package="Dao"/> </beans>

为了方便对任务调度器的管理,可以根据任务的分组和命名进行管理和批量操作,可以在Controller层,通过页面请求 对Schedule进行操作 停止 Schedule.pauseJob()

scheduler.pauseJob(JobKey.jobKey("jobName","groupName"))

重新开始 Schedule.resumeJob()

scheduler.resumeJon(JobKey.jobKey("jobName","groupName"))

删除 Schedule.deleteJob()

scheduler.deleteJob(JobKey.jobKey("jobName","groupName"))

问题:

在数据库映射数据时,数据库的生日字段使用的是data类型的存储方式,在映射的过程中可能会出现下面的错误

异常: 原因:Druid版本低,造成字段映射失败,主要是德鲁伊不支持该类型的字段映射 解决:

更新德鲁伊的版本,下载对应的映射包

或者将生日字段分开; 在设置日期是可以使用Calendar获取设置时间:

Calendar calendar=Calendar.getInstance(); //获取int型的年份 int birth_year=calendar.get(Calendar.YEAR); //获取int型的月份(0-11) int birth_month=calendar.get(Calendar.MONTH)+1; //获取对应月份的日(自动区分日期) int birth_day=calendar.get(Calendar.DAY_OF_MONTH);
最新回复(0)