首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring 整合 RabbitMQ 實現異步發送郵件:從配置到代碼完整實戰

     編輯:Java 綜合教學

業務場景

用戶註冊後,需發送歡迎郵件。為了不阻塞主流程、提升響應速度,採用「生產者寫入隊列、消費者異步發送」架構:

  1. Controller 接收註冊請求 → Service 寫入用戶表 → 發送郵件任務到 RabbitMQ → 立即返回「註冊成功」。
  2. Listener 監聽隊列 → 取出用戶信息 → 調用 JavaMail 發送郵件。

依賴引入

<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>1.6.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>

RabbitMQ 配置 (XML)

<beans xmlns="https://www.springframework.org/schema/rabbit"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://www.springframework.org/schema/rabbit
                           https://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!-- 連接工廠 -->
    <connection-factory id="connectionFactory"
        host="localhost" port="5672" username="admin" password="123456" />

    <!-- 管理 Queue/Exchange/Binding -->
    <admin connection-factory="connectionFactory" />
    <queue id="emailQueue" name="user.register.email" durable="true" />
    <direct-exchange name="user.register.exchange" durable="true">
        <bindings>
            <binding queue="emailQueue" /> <!-- routing key 默認等於 queue name -->
        </bindings>
    </direct-exchange>

    <!-- RabbitTemplate 發送 -->
    <template id="rabbitTemplate" connection-factory="connectionFactory" />

    <!-- 監聽器容器 + 消費者 -->
    <bean id="emailHandler" class="com.example.EmailHandler" />
    <listener-container connection-factory="connectionFactory" acknowledge="auto">
        <listener ref="emailHandler" method="handle" queue-names="user.register.email" />
    </listener-container>
</beans>

認證失敗排查

默認 guest/guest 僅允許 localhost。生產環境需:

  1. 開啟 Management UI (https://host:15672) → Admin → Users → Add user (administrator)。
  2. Virtual Hosts → 設定新用戶權限。
  3. 配置文件更新 username/password。

生產者:發送註冊郵件任務

@Service
public class UserAlertServiceImpl implements UserAlertService {
    private final RabbitTemplate rabbitTemplate;
    public UserAlertServiceImpl(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; }

    @Override
    public void sendRegisterEmail(User user) {
        // convertAndSend 自動序列化對象為 Message
        rabbitTemplate.convertAndSend("user.register.exchange", "user.register.email", user);
    }
}

消費者:處理郵件發送

@Component
public class EmailHandler {
    private final UserMailService mailService;
    public EmailHandler(UserMailService mailService) { this.mailService = mailService; }

    public void handle(User user) {
        mailService.sendWelcomeMail(user.getEmail(), user);
    }
}

JavaMail 配置與發送

MailSender Bean (支援 SSL/QQ/Gmail)

@Bean
public JavaMailSenderImpl mailSender(Environment env) {
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    sender.setHost(env.getProperty("mail.host"));
    sender.setPort(Integer.parseInt(env.getProperty("mail.port")));
    sender.setUsername(env.getProperty("mail.username"));
    sender.setPassword(env.getProperty("mail.password"));
    sender.setDefaultEncoding("UTF-8");

    // SSL 配置 (QQ/GMail/163 SSL)
    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.socketFactory.port", "465");
    sender.setJavaMailProperties(props);
    return sender;
}

發送簡單郵件

@Service
public class UserMailServiceImpl implements UserMailService {
    private final MailSender mailSender;
    public UserMailServiceImpl(MailSender mailSender) { this.mailSender = mailSender; }

    @Override
    public void sendWelcomeMail(String to, User user) {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom("noreply@example.com");
        msg.setTo(to);
        msg.setSubject("歡迎註冊," + user.getUsername());
        msg.setText("親愛的 " + user.getUsername() + ",感謝註冊我們的服務!");
        mailSender.send(msg);
    }
}

關鍵點總結

  • 持久化:durable="true" 確保 Queue/Exchange 重啟不丟失;消息發送端亦需 MessageDeliveryMode.PERSISTENT (Spring AMQP 默認)。
  • 確認機制:acknowledge="auto" 消費者成功處理自動 ack,異常則重回隊列。
  • 序列化:User 類實現 Serializable,字段含非序列化對象需 transient。
  • 錯誤處理:發送失敗可配置 RetryTemplate 或死信隊列 (DLX) 進一步保障。

擴展方向

  1. 引入 spring-boot-starter-amqp 簡化配置 (YAML)。
  2. 使用 @RabbitListener 註解替代 XML 監聽器定義。
  3. 郵件模板引擎 (Thymeleaf/Freemarker) 發送富文本郵件。
  4. 引入 spring-retry 實現指數退避重試。

通過 RabbitMQ 解耦「業務寫入」與「郵件發送」,系統吞吐量與穩定性顯著提升,是微服務架構中常見的異步處理模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved