Java秒杀系统实战系列~开发通用的发送邮件服务

简介: 在这篇文章中我们将继续完善秒杀系统中的核心处理逻辑,即“用户秒杀~抢单”的业务逻辑!本文我们将基于JavaMail服务,开发一个通用的发送邮件服务,用于发送邮件通知消息,并与上一篇章中已经实现的RabbitMQ异步发送消息的逻辑进行整合,彻底实现“用户秒杀成功后,异步发送邮件通知消息给到用户邮箱,告...

摘要:
本篇博文是“Java秒杀系统实战系列文章”的第九篇,在这篇文章中我们将继续完善秒杀系统中的核心处理逻辑,即“用户秒杀~抢单”的业务逻辑!本文我们将基于JavaMail服务,开发一个通用的发送邮件服务,用于发送邮件通知消息,并与上一篇章中已经实现的RabbitMQ异步发送消息的逻辑进行整合,彻底实现“用户秒杀成功后,异步发送邮件通知消息给到用户邮箱,告知用户尽快进行付款”的功能!

内容:
对于发送邮件服务,相信各位小伙伴并不陌生,本篇博文我们将开发一个通用的发送邮件服务,用于“用户秒杀成功之后异步发送邮件消息给到用户”。

(1)同样的道理,首先我们需要加入发送邮件服务的依赖,其依赖的版本号跟SpringBoot的版本号一直,为1.5.7.RELEASE,如下所示:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>${spring-boot.version}</version>
</dependency>

紧接着,我们需要在application.properties配置文件中加入“发送邮件服务”所需要的额外的支持配置信息:

#发送邮件配置
spring.mail.host=smtp.qq.com
spring.mail.username=1974544863@qq.com
spring.mail.password=cmtvsjvhonkjdaje

spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

mail.send.from=1974544863@qq.com

mail.kill.item.success.subject=商品抢购成功
mail.kill.item.success.content=您好,您已成功抢购到商品: <strong style="color: red">%s</strong> ,复制该链接并在浏览器采用新的页面打开,即可查看抢购详情:${system.domain.url}/kill/record/detail/%s,并请您在1个小时内完成订单的支付,超时将失效该订单哦!祝你生活愉快!

在本秒杀系统中,发送邮件的服务我们是采用 QQ邮箱 作为主邮箱账号,相应的SMTP服务器也是采用QQ邮箱的!其中,spring.mail.password 指的是在QQ邮箱后台开通POP3/SMTP服务 时腾讯官方给的“密钥”(授权码),在这里,Debug就贡献了上面那个密钥~授权码 给各位使用了,而真正在企业生产环境中,其实是需要去申请一个主邮箱账号的,至于如何申请,在这里就不赘述了!

(2)接下来,我们就可以大显伸手一番了!我们在MailService中开发了两种发送邮件的功能,一种发送简单文本的功能(即纯文字的、很死板、高冷风的那种),另一种是发送带HTML标签的花哨文本的功能(即带样式的、比较俏皮的、有温度的那种),如下所示:

//通用的发送邮件服务
@Service
@EnableAsync
public class MailService {
    private static final Logger log= LoggerFactory.getLogger(MailService.class);

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private Environment env;

    //发送简单文本文件
    @Async
    public void sendSimpleEmail(final MailDto dto){
        try {
            SimpleMailMessage message=new SimpleMailMessage();
            message.setFrom(env.getProperty("mail.send.from"));
            message.setTo(dto.getTos());
            message.setSubject(dto.getSubject());
            message.setText(dto.getContent());
            mailSender.send(message);

            log.info("发送简单文本文件-发送成功!");
        }catch (Exception e){
            log.error("发送简单文本文件-发生异常: ",e.fillInStackTrace());
        }
    }

    //发送花哨邮件
    @Async
    public void sendHTMLMail(final MailDto dto){
        try {
            MimeMessage message=mailSender.createMimeMessage();
            MimeMessageHelper messageHelper=new MimeMessageHelper(message,true,"utf-8");
            messageHelper.setFrom(env.getProperty("mail.send.from"));
            messageHelper.setTo(dto.getTos());
            messageHelper.setSubject(dto.getSubject());
            messageHelper.setText(dto.getContent(),true);

            mailSender.send(message);
            log.info("发送花哨邮件-发送成功!");
        }catch (Exception e){
            log.error("发送花哨邮件-发生异常: ",e.fillInStackTrace());
        }
    }
}

其中,MailDto类主要统一封装了在发送邮件时所需要的字段信息,比如接收人、邮件标题、邮件内容等等(提现了面向对象的重要特性)!其源代码如下所示:

/**统一封装了在发送邮件时所需要的字段信息
 * @Author:debug (SteadyJack)
 * @Date: 2019/6/22 10:11
 **/
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class MailDto implements Serializable{
    //邮件主题
    private String subject;
    //邮件内容
    private String content;
    //接收人
    private String[] tos;
}

(3)最后是在“RabbitMQ通用的消息接收服务类” RabbitReceiverService 的接收消息逻辑中整合进“发送邮件服务”的逻辑,如下所示:

@Autowired
private MailService mailService;

@Autowired
private Environment env;

/**
 * 秒杀异步邮件通知-接收消息
 */
@RabbitListener(queues = {"${mq.kill.item.success.email.queue}"},containerFactory = "singleListenerContainer")
public void consumeEmailMsg(KillSuccessUserInfo info){
    try {
        log.info("秒杀异步邮件通知-接收消息:{}",info);

        //TODO:真正的发送邮件....
        //简单文本
        //MailDto dto=new MailDto(env.getProperty("mail.kill.item.success.subject"),"这是测试内容",new String[]{info.getEmail()});
        //mailService.sendSimpleEmail(dto);

        //花哨文本
        final String content=String.format(env.getProperty("mail.kill.item.success.content"),info.getItemName(),info.getCode());
        MailDto dto=new MailDto(env.getProperty("mail.kill.item.success.subject"),content,new String[]{info.getEmail()});
        mailService.sendHTMLMail(dto);

    }catch (Exception e){
        log.error("秒杀异步邮件通知-接收消息-发生异常:",e.fillInStackTrace());
    }
}

(4)至此,关于通用的发送邮件服务的代码实战,我们就介绍到这里了,接下来我们进入测试环节。点击“抢购”,如果用户秒杀成功,系统后端会在数据库录入一笔秒杀成功后的订单,同时user表中“邮箱字段值”对应的邮箱会受到一封邮件,如下图所示:
image
好了,欢乐的撸码时光总是短暂的,本篇文章我们就介绍到这里了!下篇博文我们将继续我们的“秒杀系统实战”之旅!

补充:

1、由于相应的博客的更新可能并不会很快,故而如果有想要快速入门以及实战整套系统的,可以阅读: Java商城秒杀系统的设计与实战视频教程(SpringBoot版)

2、目前,这一秒杀系统的整体构建与代码实战已经全部完成了,完整的源代码数据库地址可以来这里下载:https://gitee.com/steadyjack/SpringBoot-SecondKill

相关文章
|
23天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
44 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
10天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
64 13
|
5天前
|
Java
Java基础却常被忽略:全面讲解this的实战技巧!
本次分享来自于一道Java基础的面试试题,对this的各种妙用进行了深度讲解,并分析了一些关于this的常见面试陷阱,主要包括以下几方面内容: 1.什么是this 2.this的场景化使用案例 3.关于this的误区 4.总结与练习
|
15天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
49 10
|
9天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
48 2
|
18天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
24天前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
21天前
|
Java 程序员
Java基础却常被忽略:全面讲解this的实战技巧!
小米,29岁程序员,分享Java中`this`关键字的用法。`this`代表当前对象引用,用于区分成员变量与局部变量、构造方法间调用、支持链式调用及作为参数传递。文章还探讨了`this`在静态方法和匿名内部类中的使用误区,并提供了练习题。
22 1
|
1月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
java中获取当前系统日期
java中获取当前系统日期