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

相关文章
|
8天前
|
存储 数据可视化 Java
【Java】Java swing 民宿管理系统 GUI(源码+可视化界面)【独一无二】
【Java】Java swing 民宿管理系统 GUI(源码+可视化界面)【独一无二】
|
3天前
|
人工智能 自然语言处理 Java
Spring AI,Spring团队开发的新组件,Java工程师快来一起体验吧
文章介绍了Spring AI,这是Spring团队开发的新组件,旨在为Java开发者提供易于集成的人工智能API,包括机器学习、自然语言处理和图像识别等功能,并通过实际代码示例展示了如何快速集成和使用这些AI技术。
Spring AI,Spring团队开发的新组件,Java工程师快来一起体验吧
|
8天前
|
前端开发 Oracle Java
【前端学java】java开发的依赖安装与环境配置(1)
【8月更文挑战第8天】java开发的依赖安装与环境配置
26 1
【前端学java】java开发的依赖安装与环境配置(1)
|
1天前
|
消息中间件 Java API
解密微服务架构:如何在Java中实现高效的服务通信
微服务架构作为一种现代软件开发模式,通过将应用拆分成多个独立的服务,提升了系统的灵活性和扩展性。然而,实现微服务之间的高效通信仍然是许多开发者面临的挑战。本文将探讨在Java环境中实现微服务架构时,如何使用不同的通信机制来优化服务之间的交互,包括同步和异步通信的方法,以及相关的最佳实践。
|
9天前
|
消息中间件 Java Kafka
"Kafka快速上手:从环境搭建到Java Producer与Consumer实战,轻松掌握分布式流处理平台"
【8月更文挑战第10天】Apache Kafka作为分布式流处理平台的领头羊,凭借其高吞吐量、可扩展性和容错性,在大数据处理、实时日志收集及消息队列领域表现卓越。初学者需掌握Kafka基本概念与操作。Kafka的核心组件包括Producer(生产者)、Broker(服务器)和Consumer(消费者)。Producer发送消息到Topic,Broker负责存储与转发,Consumer则读取这些消息。首先确保已安装Java和Kafka,并启动服务。接着可通过命令行创建Topic,并使用提供的Java API实现Producer发送消息和Consumer读取消息的功能。
31 8
|
6天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6天前
|
安全 前端开发 Java
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
在Web安全上下文中,源(Origin)是指一个URL的协议、域名和端口号的组合。这三个部分共同定义了资源的来源,浏览器会根据这些信息来判断两个资源是否属于同一源。例如,https://www.example.com:443和http://www.example.com虽然域名相同,但由于协议和端口号不同,它们被视为不同的源。同源(Same-Origin)是指两个URL的协议、域名和端口号完全相同。只有当这些条件都满足时,浏览器才认为这两个资源来自同一源,从而允许它们之间的交互操作。
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
|
3天前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
5天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6天前
|
IDE Java 开发工具
Java 开发神器 Lombok:告别冗余,拥抱优雅!
Java 开发神器 Lombok:告别冗余,拥抱优雅!
14 0