本節的內容是用戶注冊時,將郵箱地址先存入rabbitmq隊列,之後返回給用戶注冊成功;之後消息隊列的接收者從隊列中獲取消息,發送郵件給用戶。
一、RabbitMQ介紹
如果之前對rabbitmq不了解,推薦先看一下RabbitMQ Quick(快速手冊)。
1、rabbitmq在mac上的安裝。
2、rabbitmq簡單介紹。

生產者: 負責發送消息到Exchange。
Exchange: 按照一定的策略,負責將消息存入到指定的隊列。
隊列queue: 負責保存消息。
消費者: 負責從隊列中提取消息。
binding: 負責Exchange和隊列的關聯映射,Exchange和queue是多對多的關系。
二、RabbitMQ在Spring中的實現
1、引入依賴包。
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
2、rabbitmq配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/rabbit"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1、配置連接工廠, 如果不配置host, port, username, passowrd, 則按默認值localhost:5672, guest/guest-->
<!--<connection-factory id="connectionFactory" />-->
<connection-factory id="connectionFactory"
host="localhost"
port="5672"
username="everSeeker"
password="333" />
<!--2、配置隊列queue, Exchange, 以及將他們結合在一起的binding-->
<!--在queue以及exchange中, 有一個重要的屬性durable, 默認為true, 可以防止宕機後數據丟失。-->
<!--在listener-container中, 有acknowledge屬性, 默認為auto, 即消費者成功處理消息後必須有個應答, 如果消費者程序發生異常或者宕機, 消息會被重新放回隊列-->
<admin connection-factory="connectionFactory" />
<queue id="userAlertEmailQueue" name="user.alerts.email" durable="true" />
<queue id="userAlertCellphoneQueue" name="user.alerts.cellphone" /> <!--durable默認為true-->
<!--標准的AMQP Exchange有4種: Direct, Topic, Headers, Fanout, 根據實際需要選擇。-->
<!--Direct: 如果消息的routing key與bingding的routing key直接匹配的話, 消息將會路由到該隊列上。-->
<!--Topic: 如果消息的routing key與bingding的routing key符合通配符匹配的話, 消息將會路由到該隊列上。-->
<!--Headers: 如果消息參數表中的頭信息和值都與binding參數表中相匹配, 消息將會路由到該隊列上。-->
<!--Fanout: 不管消息的routing key和參數表的頭信息/值是什麼, 消息將會路由到該隊列上。-->
<direct-exchange name="user.alert.email.exchange" durable="true">
<bindings>
<binding queue="user.alerts.email" /> <!--默認的routing key與隊列的名稱相同-->
</bindings>
</direct-exchange>
<direct-exchange name="user.alert.cellphone.exchange">
<bindings>
<binding queue="user.alerts.cellphone" />
</bindings>
</direct-exchange>
<!--3、配置RabbitTemplate發送消息-->
<template id="rabbitTemplate"
connection-factory="connectionFactory" />
<!--4、配置監聽器容器和監聽器來接收消息-->
<beans:bean id="userListener" class="com.everSeeker.alerts.UserAlertHandler" />
<listener-container connection-factory="connectionFactory" acknowledge="auto">
<listener ref="userListener"
method="handleUserAlertToEmail"
queues="userAlertEmailQueue" />
<listener ref="userListener"
method="handleUserAlertToCellphone"
queues="userAlertCellphoneQueue" />
</listener-container>
</beans:beans>
如果配置connection-factory時,采用默認的guest/guest賬號密碼時,有可能會出現org.springframework.amqp.AmqpAuthenticationException: com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.的錯誤提示,解決辦法是新建一個管理員權限的用戶,並允許訪問虛擬主機。步驟如下:
1、打開http://localhost:15672/ 2、Admin ——> Users, 新建用戶,administrator權限。 3、Virtual Hosts,設置新建用戶允許訪問。
3、生產者發送消息到exchange。
@Service("userAlertService")
public class UserAlertServiceImpl implements UserAlertService {
private RabbitTemplate rabbit;
@Autowired
public UserAlertServiceImpl(RabbitTemplate rabbit) {
this.rabbit = rabbit;
}
public void sendUserAlertToEmail(User user) {
//convertAndSend(String exchange, String routingKey, Object object), 將對象object封裝成Message對象後, 發送給exchange
rabbit.convertAndSend("user.alert.email.exchange", "user.alerts.email", user);
}
}
4、配置消費者來接收消息。
public class UserAlertHandler {
public void handleUserAlertToEmail(User user) {
System.out.println(user);
}
三、通過javax.mail來發送郵件
1、引入依賴包。
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
2、配置郵件服務器信息。
@Bean
public MailSender mailSender(Environment env) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
//如果為普通郵箱, 非ssl認證等, 比如163郵箱
mailSender.setHost(env.getProperty("mailserver.host"));
mailSender.setPort(Integer.parseInt(env.getProperty("mailserver.port")));
mailSender.setUsername(env.getProperty("mailserver.username"));
mailSender.setPassword(env.getProperty("mailserver.password"));
mailSender.setDefaultEncoding("utf-8");
//如果郵件服務器采用了ssl認證, 增加以下配置, 比如gmail郵箱, qq郵箱
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");
mailSender.setJavaMailProperties(props);
return mailSender;
}
3、發送郵件。
@Component("userMailService")
public class UserMailServiceImpl implements UserMailService {
private MailSender mailSender;
@Autowired
public UserMailServiceImpl(MailSender mailSender) {
this.mailSender = mailSender;
}
public void sendSimpleUserMail(String to, User user) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("xxxxxxxx@qq.com");
message.setTo(to);
message.setSubject(user.getUsername() + "信息確認");
message.setText(user.toString());
mailSender.send(message);
}
}
4、消費者調用發送郵件方法即可。
1、參考文獻:Spring實戰(第4版)。
2、完整代碼在github,地址:https://github.com/everseeker0307/register。