在企業級應用開發中,郵件發送是常見的業務需求。若直接使用 JavaMail API,代碼量較大且配置繁瑣。Spring 框架提供了 MailSender 介面及其實現類 JavaMailSenderImpl,大幅簡化了郵件發送的開發流程。本文將通過完整的代碼示例,詳細講解如何利用 Spring 實現異步文本郵件發送。
在編寫代碼前,請確保專案中已引入以下核心 JAR 包:
activation.jarcommons-logging-1.0.4.jarmail.jar (JavaMail API)spring.jar (包含 spring-context、spring-context-support 等)建立 BaseMailSender 抽象類,封裝通用發送邏輯,將具體 MailSender 實例的創建延遲到子類實現:
package com.heyang.tool.mailsender;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public abstract class BaseMailSender {
protected String userName;
protected String password;
protected String stmpServer;
protected String senderEmailAddr;
/** 由子類實現,返回具體的 MailSender 實例 */
protected abstract MailSender getMailSender();
/** 發送純文本郵件 */
public final void sendMail(String to, String subject, String content) {
SimpleMailMessage msg = new SimpleMailMessage();
msg.setFrom(senderEmailAddr);
msg.setTo(to);
msg.setSubject(subject);
msg.setText(content);
getMailSender().send(msg);
}
// Setter 方法省略...
}
MailSenderImpl 繼承基類,配置 JavaMailSenderImpl 的 SMTP 參數:
package com.heyang.tool.mailsender;
import java.util.Properties;
import org.springframework.mail.MailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
public class MailSenderImpl extends BaseMailSender {
@Override
protected MailSender getMailSender() {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost(stmpServer);
sender.setUsername(userName);
sender.setPassword(password);
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", stmpServer);
sender.setJavaMailProperties(props);
return sender;
}
}
在 bean.xml 中聲明郵件發送 Bean,注入 SMTP 伺服器、帳號密碼等屬性:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="mailSender" class="com.heyang.tool.mailsender.MailSenderImpl" singleton="false">
<property name="userName" value="your_email@163.com"/>
<property name="password" value="your_password"/>
<property name="stmpServer" value="smtp.163.com"/>
<property name="senderEmailAddr" value="your_email@163.com"/>
</bean>
</beans>
使用 Runnable + Thread 實現非阻塞發送,避免影響主業務流程響應速度:
package com.heyang.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.heyang.tool.mailsender.BaseMailSender;
import com.heyang.tool.mailsender.MailSenderImpl;
import java.util.List;
public final class MailUtil {
/** 異步發送單封郵件 */
public static void sendMail(final String to, final String title, final String content) {
new Thread(() -> {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
BaseMailSender sender = (MailSenderImpl) ctx.getBean("mailSender");
sender.sendMail(to, title, content);
}).start();
}
/** 異步群發郵件給支援團隊 */
public static void sendMailToSupporters(final String title, final String content) {
new Thread(() -> {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
BaseMailSender sender = (MailSenderImpl) ctx.getBean("mailSender");
// 假設 SupportTeam Bean 已配置並提供郵箱列表
// SupportTeam team = (SupportTeam) ctx.getBean("supportTeam");
// List mails = team.getSupporterEmails();
// for (String addr : mails) sender.sendMail(addr, title, content);
}).start();
}
public static void main(String[] args) {
sendMailToSupporters("測試標題", "測試內容");
}
}
BaseMailSender 定義發送骨架,MailSenderImpl 實現具體創建邏輯,符合開閉原則。ApplicationContext,生產環境建議改為單例模式或使用 @Async 註解配合線程池。getMailSender() 即可切換不同郵件服務商(QQ、Gmail、企業郵箱等)。@Async + ThreadPoolTaskExecutor 替代手動 new Thread(),避免線程無限制創建導致 OOM。JavaMailSenderImpl 配置為單例 Bean,注入到 Service 中複用,減少上下文啟動開銷。MimeMessageHelper。