一、设计与接口定义
我们首先从控制器层开始设计,定义一个名为MailboxCollection
的接口,为发送邮箱验证码提供统一的入口。此接口清晰地描述了其职责:
/**
* @author 青衫烟雨客
* @version 1.0
* @description 描述: 邮箱验证码发送接口类,实现简单文本验证码的发送功能
* ...
*/
public interface MailboxCollection {
R putCode(EmailRequest emailRequest) throws MessagingException, UnsupportedEncodingException;
}
putCode
方法接收一个封装了邮箱信息的EmailRequest
对象作为参数,并通过R
对象返回操作结果。接口文档中明确指出了可能出现的异常情况,包括邮件发送过程中的通信错误(jakarta.mail.MessagingException
)和编码格式不支持的问题(UnsupportedEncodingException
)。这种严谨的设计确保了接口使用者对潜在风险有清晰的认知,也为后续异常处理提供了指导。
二、实现控制器逻辑
接着,我们创建一个名为mailboxController
的RESTful控制器,实现MailboxCollection
接口。通过@RestController
注解,我们将这个类标记为处理HTTP请求并直接返回JSON响应的控制器。同时,使用@RequestMapping("/sendCode")
注解将所有方法的请求路径映射到/sendCode
。
@RestController
@Slf4j
@RequestMapping("/sendCode")
public class mailboxController implements MailboxCollection {
...
}
在控制器中,我们关注的是putCode
方法的实现。该方法接收前端POST请求的EmailRequest
对象,调用mailBoxServiceImp
服务类完成验证码发送,并返回封装了发送结果的状态和数据的R
对象。为了处理可能出现的异常,我们采用日志记录异常详情,并返回带有内部服务器错误状态码和错误信息的响应。
三、抽象服务层接口
为了遵循“单一职责原则”和便于单元测试,我们将邮件发送的具体逻辑封装在服务层。定义MailBoxService
接口,声明一个sendEmail
方法,接受EmailRequest
参数并返回发送验证码的结果字符串。
public interface MailBoxService {
String sendEmail(EmailRequest emailRequest) throws MessagingException, UnsupportedEncodingException;
}
四、实现服务层逻辑
接下来,我们实现MailBoxService
接口,创建mailBoxServiceImp
类。该类依赖于Spring的JavaMailSender
接口,用于实际发送邮件。同时,从配置文件中注入发件人信息、邮件主题前缀和后缀等配置项。
@Service
@Slf4j
public class mailBoxServiceImp implements MailBoxService {
...
}
sendEmail
方法内,我们按照以下步骤执行:
-
初始化邮件消息:使用
javaMailSender.createMimeMessage()
创建MimeMessage
对象,通过MimeMessageHelper
设置邮件的多部分属性。 -
配置发件人与收件人信息:从
EmailRequest
中提取收件人邮箱地址和邮件主题,并设置发件人的用户名和显示名。 -
生成验证码:调用
generateRandomCode(5)
生成长度为5位的随机验证码。 -
构建邮件正文:将验证码拼接成完整的邮件正文,包括预定义的文本前缀和后缀。
-
发送邮件:调用
javaMailSender.send(mimeMessage)
发送构建好的邮件。 -
返回验证码:将生成的验证码作为方法返回值,供后续验证使用。
五、配置邮件服务
最后,我们在Spring Boot的配置文件中添加必要的邮件服务设置:
mail:
host: smtp.qq.com
port: 465
addressName: 邮箱主题
username: 邮箱地址
password: 邮箱秘钥
TextHeader: 您的验证码是
TextEnd: 邮件验证码的后半段
...
这些配置涵盖了SMTP服务器地址、端口、认证信息、邮件主题文本等内容,确保邮件服务能够正确连接到指定的邮件服务器并进行身份验证。
这个是后端响应模板
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static @NotNull R success() {
return new R(1, "success" , null);
}
//查询 成功响应
public static @NotNull R success(Object data) {
return new R(1, "success" , data);
}
//失败响应
public static @NotNull R error(String msg) {
return new R(0, msg, null);
}
}