前言

Hutool 是一个小而全的Java工具类库,它帮助我们简化每一行代码,避免重复造轮子,提高了工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以 “甜甜的”
最近在使用Hutool工具类中的邮件发送的工具类时,遇到了一个小问题,通过这个问题找到了Hutool工具类的一个 “bug”

文章的主线:

1、介绍下使用Hutool中邮件发送工具类时出现的问题;

2、聊聊问题排查的过程;

问题描述

在描述出现的问题前,先简单将出现问题时项目的情况介绍下。

项目情况:

本项目是一个web项目,有一些前台页面,例如,邮件配置页面,在此页面配置一些邮件发送的参数,配置发件人邮箱、密码、收件人邮箱等数据,然后将其存储到数据库表中。

程序内部在每次发送邮件时,都会去数据库中重新读取邮件配置参数,然后使用新的配置参数发送邮件;

但是在此出现了问题,在第一次发送报警邮件时,配置的收件人是一个,后来将收件人的参数改为了两个人,然后再发送报警邮件时,还是只有之前配置的那个收件人可以收到邮件,新配置的另一个收件人没有收到邮件;why,为什么?

发送邮件的伪代码:

// 去数据库中查询邮件配置参数
MailConfigBean mailConfigBean = DaoUtil.getConfigBean();
// 组装邮件配置参数
MailAccount account = new MailAccount();
account.setHost(mailConfigBean.getHost());
account.setPort(mailConfigBean.getPort());
account.setAuth(mailConfigBean.isIfAuth());
account.setFrom(mailConfigBean.getFrom());
account.setUser(mailConfigBean.getFrom());
account.setPass(mailConfigBean.getPassword());
// 邮件发送
MailUtil.send(account, CollUtil.newArrayList("hutool@foxmail.com"), "测试", "Hutool测试", false);
以上代码是在 Hutool 官网上直接拿来使用的,按理说应该是没有任何问题。

排查过程

正如上面描述的,刚开始时确实不太清楚可能会导致出现问题的原因,但是慢慢理理思路后,开始按照下面的方式进行了排查:

自写代码排查:

遇到这个问题我首先质疑的是自己的代码是否存在问题,是否自己在修改了邮件的配置参数后程序没有去重新读取配置,但是通过debug发现自己的代码没有问题。

邮件工具类源码:

然后去看了看这个工具类的源代码发现了问题所在;

这个工具类中有个参数 "isUseGlobalSession" (是否使用全局session),工具类代码中的 "send()" 邮件发送方法中 "isUseGlobalSession = true" 默认为使用的,所以导致即使重新读取了修改后的邮件配置也是使用的之前的配置参数。

源码查看过程:

①、点击下面邮件发送的send的方法:

// 邮件发送
MailUtil.send(account, CollUtil.newArrayList("hutool@foxmail.com"), "测试", "Hutool测试", false);

②、进入到send方法内:

public static void send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
        Mail.create(mailAccount).setTos((String[])tos.toArray(new String[tos.size()])).setTitle(subject).setContent(content).setHtml(isHtml).setFiles(files).send();
    }

③、点击mail.create(),进入createts方法内:

public static Mail create(MailAccount mailAccount) {
        return new Mail(mailAccount);
}

④、最后进入到Mail 的构造方法内:

public Mail(MailAccount mailAccount) {
    // 发现这里useGlobalSession默认是true,所以导致一直使用原来的配置参数
   this.useGlobalSession = true;
   mailAccount = null != mailAccount?mailAccount:GlobalMailAccount.INSTANCE.getAccount();
   this.mailAccount = mailAccount.defaultIfEmpty();
}

解决方法

问题找到后,就需要根据问题原因实现解决方案了;这个问题是由于使用了默认的全局session导致的,所以只需要重写 send 方法,设置不使用全局session即可;

具体步骤:

①、新建一个"SendMailUtil"工具类,然后继承Hutool中的"MailUtil"类;

②、然后重写 "send()" 方法,在send方法中默认不使用其全局session;

③、然后在发送报警邮件时调用此重写的send方法即可;

代码:

public class SendMailUtil extends MailUtil{
 
    /**
     *  重写send方法让其不使用全局会话
     *
     *  setUseGlobalSession(false);设置是否使用全局会话为 false
     */
    public static void send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
        Mail.create(mailAccount).setTos((String[])tos.toArray(new String[tos.size()])).setTitle(subject).setContent(content).setHtml(isHtml).setUseGlobalSession(false).setFiles(files).send();
    }
 
}
end. . . 本文结束了;通过本文,想给大家一个建议:多阅读下源码,帮助很大。

❤不要忘记留下你学习的足迹 [点赞 + 收藏 + 评论]嘿嘿ヾ

一切看文章不点赞都是“耍流氓”,嘿嘿ヾ(◍°∇°◍)ノ゙!开个玩笑,动一动你的小手,点赞就完事了,你每个人出一份力量(点赞 + 评论)就会让更多的学习者加入进来!非常感谢! ̄ω ̄=;最后说VX搜索【木子雷】某众号,一起学习呀!

木子雷
213 声望268 粉丝

Web后端码仔,记录生活,分享技术!