spring-boot - 使用 Quartz 和 Spring boot 安排任务
问题描述
我想每天使用 Spring boot 发送电子邮件,用户指定发送时间,我使用石英来安排我的工作。电子邮件的收件人有(id,emailAddress,deadline) 电子邮件将发送给有deadline = Today + X..(用户指定X)的人。例如:用户指定 X 是数字 1,所以我们对明天有截止日期的人感兴趣。
第 1 天:应用程序向截止日期 = 今天 +1 的人发送电子邮件。第 2 天:我希望应用程序在第 2 天将电子邮件发送给新的收件人,但是使用下面的代码,电子邮件会发送给收到它的人Day1,这不是我需要的。
@PostMapping("/scheduleEmailPeriodic")
public ResponseEntity<ScheduleEmailResponse> SendScheduleEmailPeriodic(
@Valid @RequestBody PeriodicNotification scheduleEmailRequest) throws Exception {
ens.schedulePeriodicNotification(scheduleEmailRequest);
LocalDate localDateTime = LocalDate.now();
LocalTime localTime = LocalTime.parse(scheduleEmailRequest.getSendingTime());
try {
ZonedDateTime dateTime = ZonedDateTime.of(localDateTime, localTime,ZoneId.of("Africa/Casablanca"));
if (dateTime.isBefore(ZonedDateTime.now())) {
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"dateTime must be after current time");
return ResponseEntity.badRequest().body(scheduleEmailResponse);
}
JobDetail jobDetail = buildPeriodicJobDetail(scheduleEmailRequest);
Trigger trigger = buildJobTriggerPeriodic(jobDetail, dateTime);
scheduler.scheduleJob(jobDetail, trigger);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(true, jobDetail.getKey().getName(),
jobDetail.getKey().getGroup(), "Email Scheduled Successfully!");
return ResponseEntity.ok(scheduleEmailResponse);
} catch (SchedulerException ex) {
logger.error("Error scheduling email", ex);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"Error scheduling email. Please try later!");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(scheduleEmailResponse);
}
}
private JobDetail buildPeriodicJobDetail(PeriodicNotification scheduleEmailRequest) {
JobDataMap jobDataMap = new JobDataMap();
List<String> recipients = fileRepo.findWantedEmails(scheduleEmailRequest.getDaysNum());
if(recipients.isEmpty()) {
throw new RuntimeException("Aucun destinataire trouvé");
}
String[] to = recipients.stream().toArray(String[]::new);
jobDataMap.put("recipients", to);
jobDataMap.put("subject", scheduleEmailRequest.getSubject());
jobDataMap.put("body", scheduleEmailRequest.getMessage());
return JobBuilder.newJob(EmailJob.class).withIdentity(UUID.randomUUID().toString(), "email-jobs")
.withDescription("Send Email Job").usingJobData(jobDataMap).storeDurably().build();
}
private Trigger buildJobTriggerPeriodic(JobDetail jobDetail, ZonedDateTime startAt) {
return TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(), "email-triggers")
.withDescription("Send Periodic Email Trigger")
.withSchedule(SimpleScheduleBuilder
.repeatHourlyForever(24))
.startAt(Date.from(startAt.toInstant()))
.build();
}
这是电子邮件工作:
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Executing Job with key {}", context.getJobDetail().getKey());
JobDataMap jobDataMap = context.getMergedJobDataMap();
String subject = jobDataMap.getString("subject");
String body = jobDataMap.getString("body");
String[] recipients = (String[])jobDataMap.get("recipients");
sendMail("smsender4@gmail.com", recipients, subject, body);
}
private void sendMail(String fromEmail, String[] toEmail, String subject, String body) {
try {
logger.info("Sending Email to {}", Arrays.toString(toEmail));
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, StandardCharsets.UTF_8.toString());
messageHelper.setSubject(subject);
messageHelper.setText(body, true);
messageHelper.setFrom(fromEmail);
messageHelper.setTo(toEmail);
mailSender.send(message);
} catch (MessagingException ex) {
logger.error("Failed to send email to {}", Arrays.toString(toEmail));
}
}
}
我真的需要帮助,我每天都需要获得新的收件人,而不是将电子邮件发送给相同的收件人。
解决方案
您正在根据日期发送电子邮件 - 但您不会跟踪为特定用户发送电子邮件的时间。因此,如果您今天向 user1 发送一封电子邮件 - 那么 user1 仍然处于第二天的状态。您需要添加一个标志(或其他一些逻辑),说明已为此用户发送了电子邮件
推荐阅读
- javascript - 如何添加过滤器以创建从一个栏到另一个栏的单个路径(不在循环中)
- r - 如何将三角形添加到 R 中的 ggplot2 颜色条以指示超出范围的值?
- javascript - 为什么此代码更改字符串但又恢复到原始状态
- odoo - 如何禁用其他用户的更改密码选项?
- typescript - Typescript assumes the property type to be T | Properties["key"] instead of just T
- c++ - 就地创建和填充数组
- antlr4 - 如何解析无法转换为解析器规则的长词法规则的标记?
- hybris - 基于从 FlexQuery 获得的 PK 导入 Hybris Impex
- python-3.x - Python,将字典转换为逗号分隔值
- model - 如何使用 OR-Tools for python 描述目标大于零