首页 > 编程 > Java > 正文

Spring boot搭建邮件服务的完整步骤

2019-11-26 08:35:14
字体:
来源:转载
供稿:网友

前言:

发送邮件,肯定是每个公司都会有的基本业务。很多公司都会选择把发送邮件作为一个基础服务,对外提供接口。直接调用就可发邮件了。但是我们都知道发送邮件耗时都比较长。那么今天就介绍下使用Spring boot+eventbus来打造一个简单邮件服务

规划接口列表

发送邮件的类型准备的有三种

  • 发送普通邮件
  • 发送html邮件
  • 发送图文邮件

还有一个细节,如果我们同步的取发送邮件会有两个问题。

  • 接口响应时间比较长
  • 遇到并发的情况,容易导致服务器压力过大或者邮箱服务封ip

所以我们准备使用队列来执行发送邮件的操作。可以解决这个问题。队列我选用的是Google的eventbus。是一款很轻量的队列。直接走的内存

准备工作

首先要在pom.xml中引入 需要使用的包

 <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency>   <groupId>com.google.guava</groupId>   <artifactId>guava</artifactId>   <version>23.0</version>  </dependency>  <dependency>   <groupId>org.projectlombok</groupId>   <artifactId>lombok</artifactId>  </dependency>
  • spring-boot-starter-mail :spring-boot提供的发邮件的maven库
  • guava:google提供的开源库。里面包含来很多工具
  • lombok:可以帮你省去编写实体类的工具

引入之后,我们还需要配置发送邮件所需要的必要配置

在application.properties中配置邮箱

spring.mail.host=smtp.mail.me.com //邮箱发送服务器spring.mail.port=587//服务器端口spring.mail.username=xxx6666@icloud.com//发件人邮箱spring.mail.password=password//客户端专用密码//如果和我一样使用的icloud邮箱 还需要下列两个配置,别的有的邮箱不需要spring.mail.properties.mail.smtp.starttls.enable=truespring.mail.properties.mail.smtp.starttls.required=true

做到这里其实就已经完成了,发邮件所需要的配置了。但是我们是要用队列来发送,所以还需要配置下队列

@Configurationpublic class AsyncEventBusConfig { //实例化bean,采用单例形式注入容器 @Bean @Scope("singleton") public AsyncEventBus asyncEventBus(){  //创建线程池对象  final ThreadPoolExecutor executor=executor();  return new AsyncEventBus(executor); } //创建线程池方法 private ThreadPoolExecutor executor(){  return new    ThreadPoolExecutor(2,    2,0L,    TimeUnit.MICROSECONDS,    new LinkedBlockingQueue<>()); }}

封装EmailService

准备好了之后,就可以直接来封装发送邮件的业务了。之前有提到我们需要三个接口,同样的,我们也需要三个service方法

@Servicepublic class EmailService { @Autowired private JavaMailSender javaMailSender; /**  * 发件人。这里发件人一般是同使用的发件邮箱一致  */ @Value("${spring.mail.username}") private String from; /**  * 发送文本邮件  * @param to 收件人邮箱地址  * @param subject 主题  * @param content 内容  */ public void sendTextMail(String to,        String subject,        String content) {  SimpleMailMessage simpleMailMessage = new SimpleMailMessage();  simpleMailMessage.setTo(to);  simpleMailMessage.setSubject(subject);  simpleMailMessage.setText(content);  simpleMailMessage.setFrom(from);  javaMailSender.send(simpleMailMessage); } /**  * 发送html内容的邮件  * @param to 收件人  * @param htmlContent html内容  * @param subject 主题  * @throws MessagingException  */ public void sendHtmlMail(String to,        String htmlContent,        String subject) throws MessagingException {  MimeMessage message = javaMailSender.createMimeMessage();  MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);  messageHelper.setTo(to);  messageHelper.setSubject(subject);  messageHelper.setFrom(from);  messageHelper.setText(htmlContent, true);  javaMailSender.send(message); } /**  * 发送图文邮件  * @param to 收件人  * @param imgContent 图文内容  * @param subject 主题  * @param rscId 资源id  * @param imgPath 资源路径  * @throws MessagingException  */ public void sendImgMail(String to,       String imgContent,       String subject,       String rscId,       String imgPath) throws MessagingException {  MimeMessage message = javaMailSender.createMimeMessage();  MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);  messageHelper.setTo(to);  messageHelper.setSubject(subject);  messageHelper.setFrom(from);  messageHelper.setText(imgContent, true);  messageHelper.addInline(rscId, new File(imgPath));  javaMailSender.send(message); }}

队列监听

既然封装好了方法,那么就需要调用。调用的方式,其实就是将接口传来的数据传到队列里。队列的消费者接收到了消息就将消息拿来调用发送邮件的方法

我们首先创建一个消费类,用来接受消息,处理消息。

@Servicepublic class EventBusListener { /**  * 引入bean  */ @Autowired private AsyncEventBus asyncEventBus; @Autowired private EmailService emailService; /**  * 注册服务类  */ @PostConstruct public void init(){  asyncEventBus.register(this); } /**  * 线程安全,消费 文本消息  * @param textEmailDTO  */ @AllowConcurrentEvents @Subscribe public void sendTextMail(TextEmailDTO textEmailDTO){  emailService.sendTextMail(    textEmailDTO.getTo(),    textEmailDTO.getSubject(),    textEmailDTO.getContent()  ); } /**  * 线程安全 消费 html消息  * @param htmlEmailDTO  */ @AllowConcurrentEvents @Subscribe public void sendHtmlMail(HtmlEmailDTO htmlEmailDTO){  try {   emailService.sendHtmlMail(     htmlEmailDTO.getTo(),     htmlEmailDTO.getHtmlContent(),     htmlEmailDTO.getSubject()   );  } catch (MessagingException e) {   // nothing to do  } } /**  * 线程安全 消费 图文消息  * @param imgEmailDTO  */ @AllowConcurrentEvents @Subscribe public void sendImgMail(ImgEmailDTO imgEmailDTO){  try {   emailService.sendImgMail(     imgEmailDTO.getTo(),     imgEmailDTO.getImgContent(),     imgEmailDTO.getSubject(),     imgEmailDTO.getRscId(),     imgEmailDTO.getImgPath()   );  } catch (MessagingException e) {   // nothing to do  } }}

其实eventbus抛消息都是使用的post方法来抛消息。走到不同的方法里面是利用了类的多态,抛入不同的实体类就可以进行区分了。走进了不同的方法,就调用相应Service方法。

控制器与测试

控制器部分,没什么好说的,我就贴出图文的代码。其余代码可以在我的github上面看

先看眼实体类

@Datapublic class ImgEmailDTO implements Serializable { public ImgEmailDTO() { } /**  * 图片路径  */ private String imgPath; /**  * 资源id  */ private String rscId; /**  * 主题  */ private String subject; /**  * 图片正文(同样可以使用html)  */ private String imgContent; /**  * 收件人  */ private String to;}
 /**  * 发送图文邮件  * @param request  * @return  */ @RequestMapping(value = "/sendImgMail", method = RequestMethod.POST) public Result<Integer> sendImgMail(@RequestBody Request<ImgEmailDTO> request) {  Result<Integer> result = Result.create();  ImgEmailDTO imgEmailDTO=request.getData();  StringBuilder sb=new StringBuilder();  sb.append(imgEmailDTO.getImgContent());  //cid:资源id。在spring中会自动绑定  sb.append("<img src=/'cid:").append(imgEmailDTO.getRscId()).append("/'></img>");  imgEmailDTO.setImgContent(sb.toString());  asyncEventBus.post(imgEmailDTO);  return result.success(1); }

图文要稍微特殊一点,需要拼接下正文内容。然后将实体类中的content替换。最后将实体类抛入队列。直接返回接口请求。队列那边就会排着队搞定所有的邮件

下面来做个测试

请求很迅速的返回了结果

然后去邮箱中查看结果

好了今天对邮件服务的介绍就写到这里。知识点并不深奥,主要介绍一个思路。如有不对的地方,请大神指出。谢谢

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对武林网的支持。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表