在开发过程中,我们经常需要使用邮件服务来发送电子邮件通知、验证码等信息。邮件服务的配置可能会因为不同的需求而变化,例如加密方式、协议等。因此在这篇博客中,我们将讨论如何使用单例模式来实现邮件发送服务的动态配置,以满足不同需求的灵活性和可扩展性。
首先,让我们来考虑一个场景:我们的应用程序需要发送电子邮件,但是邮件服务的配置可能会经常变化,例如加密方式从 SSL 切换到 TLS,或者使用不同的协议。为了解决这个问题,我们可以使用实例池模式来管理邮件发送服务的实例,并根据需要动态更新配置。
import com.sun.mail.util.MailSSLSocketFactory;
import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class EmailSender {
private static volatile EmailSender instance;
private Session session;
private EmailSender() throws GeneralSecurityException {
configureSession("SSL", "smtp");
}
public static EmailSender getInstance() throws GeneralSecurityException {
if (instance == null) {
synchronized (EmailSender.class) {
if (instance == null) {
instance = new EmailSender();
}
}
}
return instance;
}
public void updateConfiguration(String encryptionType, String protocol) throws GeneralSecurityException {
configureSession(encryptionType, protocol);
}
private void configureSession(String encryptionType, String protocol) throws GeneralSecurityException {
Properties properties = new Properties();
properties.setProperty("mail.transport.protocol", protocol);
properties.setProperty("mail.smtp.auth", "true");
switch (encryptionType) {
case "None":
properties.setProperty("mail.smtp.ssl.enable", "false");
properties.setProperty("mail.smtp.starttls.enable", "false");
break;
case "SSL":
properties.setProperty("mail.smtp.ssl.enable", "true");
properties.setProperty("mail.smtp.starttls.enable", "false");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.socketFactory", sf);
break;
case "TLS":
properties.setProperty("mail.smtp.ssl.enable", "false");
properties.setProperty("mail.smtp.starttls.enable", "true");
break;
}
session = Session.getInstance(properties);
session.setDebug(false);
}
public void sendEmail(String recipient, String subject, String content) throws MessagingException {
Transport transport = session.getTransport();
transport.connect("smtp.qq.com", "xxx@qq.com", "xxx");
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setFrom(new InternetAddress("xxx@qq.com"));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
mimeMessage.setSubject(subject);
mimeMessage.setContent(content, "text/html;charset=UTF-8");
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
transport.close();
}
public static void main(String[] args) throws GeneralSecurityException, MessagingException {
EmailSender emailSender = EmailSender.getInstance();
emailSender.sendEmail("xxx@163.com", "Test Email", "发送SSL邮箱.");
emailSender.updateConfiguration("TLS", "");
emailSender.sendEmail("xxx@163.com", "Modified Test Email", "发送TLS邮箱.");
emailSender = EmailSender.getInstance();
emailSender.sendEmail("xxx@163.com", "Modified Test Email", "发送TLS邮箱.");
}
}
在上面的代码中,我们创建了一个名为 EmailSender 的类,它负责发送电子邮件。这个类采用了单例模式。当调用 getInstance 方法获取实例时,如果实例不存在,则会重新创建一个;否则,直接已有的实例。同时,我们定义了一个 session 成员变量,用于保存邮件发送的会话信息。updateConfiguration 方法允许动态更新配置,例如更改加密方式或协议。每次更新配置时,我们会重新配置邮件发送的会话。
测试
在 main 方法中,我们演示了如何使用 EmailSender 类来发送电子邮件,并动态更新配置。我们首先发送一封使用 SSL 加密方式的电子邮件,然后通过 updateConfiguration 方法将加密方式修改为 TLS,并发送一封使用 TLS 加密方式的电子邮件。最后,我们再次获取 EmailSender 实例,并发送一封新的电子邮件,以验证工作原理。
通过使用单例模式,我们可以确保在应用程序的整个生命周期内,只会创建一个 EmailSender 实例,并且能够动态地更新配置,以满足不同需求的灵活性。
具体实现效果可在RuoYi-Vue-Plus多租户管理系统平台登录体验
租户:体验租户
用户名:cxks
密码: cxks123