今天在看PiggyMetrics开源项目的源代码时发现邮件提醒模块的代码写的很性感,分享一下大家一起进步。
- application.yml 邮件模板设置
remind:
cron: 0 0 0 * * *
email:
text: "Hey, {0}! We''ve missed you here on PiggyMetrics. It''s time to check your budget statistics.\r\n\r\nCheers,\r\nPiggyMetrics team"
subject: PiggyMetrics reminder
- 通知类型 NotificationType
public enum NotificationType {
BACKUP("backup.email.subject", "backup.email.text", "backup.email.attachment"),
REMIND("remind.email.subject", "remind.email.text", null);
- 通知设置 NotificationSettings
public class NotificationSettings {
@NotNull
private Boolean active;
@NotNull
private Frequency frequency;
private Date lastNotified;
- 频次实体 Frequency
public enum Frequency {
WEEKLY(7), MONTHLY(30), QUARTERLY(90);
private int days;
Frequency(int days) {
this.days = days;
}
public int getDays() {
return days;
}
public static Frequency withDays(int days) {
return Stream.of(Frequency.values())
.filter(f -> f.getDays() == days)
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
这里时间周期采用枚举类十分巧妙,提醒频次分为一周,一月,三月。根据日期查询频次也是利用了jdk8的新特性,活学活用啊。
- 收件人实体 Recipient
public class Recipient {
@Id
private String accountName;
@NotNull
@Email
private String email;
@Valid
private Map<NotificationType, NotificationSettings> scheduledNotifications;
这里通过一个map把不同类型的邮件管理了起来,把一个用户拥有不同类型的邮件内容很简洁的设计了出来,非常聪明的做法,不得不赞扬一下啊。
-
看看最终数据库存储结构
-
发送邮件
@Scheduled(cron = "${remind.cron}")
public void sendRemindNotifications() {
final NotificationType type = NotificationType.REMIND;
List<Recipient> recipients = recipientService.findReadyToNotify(type);
log.info("found {} recipients for remind notification", recipients.size());
recipients.forEach(recipient -> CompletableFuture.runAsync(() -> {
try {
emailService.send(type, recipient, null);
} catch (Throwable t) {
log.error("an error during remind notification for {}", recipient, t);
}
}));
}
非常完美的代码,还利用上了CompletableFuture。这个东西太强了,后面再深入研究。