1.使用 docker 下載 rabbitmq :
docker pull rabbitmq:management
2.使用 docker images 命令來查看下載的鏡像:
$ docker images
3.使用 docker start 命令來啓動rabbitmq:
docker start 9822b13b4f75
4.構建項目
5. umz-message-api 接口工程
1.api接口類RegisterServiceApi
#定義接口類
package com.microservice.soa.api.register;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import com.microservice.soa.bean.email.EmailRequestBean;
import com.microservice.soa.bean.email.EmailResponseBean;
public interface RegisterServiceApi {
/**
*
* @Title: queryOrderInfo
* @Description: TODO(註冊發送郵件)
* @param @param emailRequestBean
* @param @return 參數
* @return String 返回類型
* @throws
*/
// @RequestMapping("sendEmail")
public EmailResponseBean sendMessage(@RequestBody EmailRequestBean emailRequestBean);
}
package com.microservice.soa.bean.email;
import java.io.Serializable;
/**
*
* @ClassName: EmailRequestBean
* @Description: TODO(郵箱請求實體類)
* @author MAOJIAJIE
* @date 2019年4月19日
*
*/
public class EmailRequestBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String uname;//收件人性名
private String upassword;//收件人密碼
private String uregdate; //註冊時間
private Integer ustate;//狀態
private String fromAddress; //發件人
private String toAddress; //收件人
private String text; //郵件標題
private String content; //郵件內容
private String copyPerson; //抄送人
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpassword() {
return upassword;
}
public void setUpassword(String upassword) {
this.upassword = upassword;
}
public String getUregdate() {
return uregdate;
}
public void setUregdate(String uregdate) {
this.uregdate = uregdate;
}
public Integer getUstate() {
return ustate;
}
public void setUstate(Integer ustate) {
this.ustate = ustate;
}
public String getFromAddress() {
return fromAddress;
}
public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}
public String getToAddress() {
return toAddress;
}
public void setToAddress(String toAddress) {
this.toAddress = toAddress;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCopyPerson() {
return copyPerson;
}
public void setCopyPerson(String copyPerson) {
this.copyPerson = copyPerson;
}
@Override
public String toString() {
return "EmailRequestBean [uname=" + uname + ", upassword=" + upassword + ", uregdate=" + uregdate + ", ustate="
+ ustate + ", fromAddress=" + fromAddress + ", toAddress=" + toAddress + ", text=" + text + ", content="
+ content + ", copyPerson=" + copyPerson + "]";
}
}
###########################################################################
package com.microservice.soa.bean.email;
import com.microservice.soa.bean.BaseRespBean;
/**
*
* @ClassName: EmailRequestBean
* @Description: TODO(郵箱返回實體類)
* @author MAOJIAJIE
* @date 2019年4月19日
*
*/
public class EmailResponseBean extends BaseRespBean {
private static final long serialVersionUID = 1L;
private String msg;
private String toAddress;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getToAddress() {
return toAddress;
}
public void setToAddress(String toAddress) {
this.toAddress = toAddress;
}
@Override
public String toString() {
return "EmailResponseBean [msg=" + msg + ", toAddress=" + toAddress + "]";
}
}
6. umz-message工程
相關的配置
1.application.yml
#配置yml
# native
#應用端口及應用名稱
server:
port: 8009
servlet:
context-path: /umz-message
#數據庫配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/dumz_db?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 12345678
type: com.alibaba.druid.pool.DruidDataSource
tomcat:
initial-size: 1
max-wait: 60000
min-idle: 3
max-age: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
mvc:
view:
prefix: /WEB-INF/
suffix: .jsp
http:
encoding:
charset: UTF-8
enabled: true
force: true
#郵箱服務器
mail:
host: smtp.qq.com
#發送郵箱用戶名
username: [email protected]
#此處爲客戶端授權密碼
password: kmwptnlpeznjebaj
#編碼集
default-encoding: UTF-8
#必須有!郵箱授權開啓,不然報錯
properties:
mail:
smtp:
auth: true
#服務器地址校正
localhost: smtp.qq.com
application:
name: umz-message #客戶端服務名
# redis:
# database: 0 #Redis數據庫索引(默認爲0)依次遞增
# host: 127.0.0.1 #Redis服務器地址
# port: 6379 #Redis服務器連接端口
# lettuce:
# pool:
# max-active: 8 #最大連接數
# max-wait: -1s #最大阻塞等待時間(負數表示沒限制)
# max-idle: 8 #最大空閒數
# min-idle: 0 #最小空閒數
# timeout: 10000s #連接超時時間
# jedis: #springboot2.0 中直接使用jedis或者lettuce配置連接池
# pool:
# max-active: 10 #最大連接數 負數爲不限制
# max-wait: -1s #連接池最大阻塞等待時間(使用負值表示沒有限制) 等待可用連接的最大時間,負數爲不限制
# max-idle: 8 #連接池中的最大空閒連接
# min-idle: 0 #連接池中的最小空閒連接
# timeout: 10000ms #設置連接超時時間
#消息隊列
rabbitmq:
host: 127.0.0.1
port: 5672
username: admin
password: admin
### 地址
virtual-host: /
#註冊信息
eureka:
instance:
hostname: localhost #eureka客戶端主機實例名稱
instance-id: umz-message:8762 #客戶端實例名稱
prefer-ip-address: true #顯示IP
lease-renewal-interval-in-seconds: 1 #eureka 客戶端向服務端發送心跳間隔時間 單位秒
lease-expiration-duration-in-seconds: 2 #eureka服務端收到最後一次等筆
client:
service-url:
defaultZone: http://localhost:8761/eureka/
# 單機 defaultZone: http://localhost:2001/eureka #把服務註冊到eureka註冊中心
#defaultZone: http://eureka2001.java1234.com:2001/eureka/,http://eureka2002.java1234.com:2002/eureka/,http://eureka2003.java1234.com:2003/eureka/ # 集羣
mybatis:
mapper-locations:
- classpath:com/microservice/soa/dao/*.xml
config-location: classpath:com/microservice/mybatis-config.xml
type-aliases-package: com.microservice.soa.model
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #可以指定相應的類
## 健康狀態 http://localhost:9001/microConsumer/health
#info:
# app:
# name: "@project.artifactId@"
# encoding: "@project.build.sourceEncoding@"
# java:
# source: "@java.version@"
# target: "@java.version@"
#logging:
# config: classpath:log4j2.xml
2.RabbitConfig配置類
package com.microservice.soa.conf;
import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
//爲了方便演示我都使用的public
//隊列
public static final String EMAIL_QUEUE = "emailQueue";
//交換機
public static final String EXCHANGE_TOPIC_NAME = "testChange";
//#路由規則 匹配 email後面 所有的鍵
public static final String QUEUE_BING_ROUTINGKEY="email.#";
//# 提供者發送消息指定的 路由鍵(郵件)
public static final String PRODUCER_ROUTINGKEY="email.bar.test";
//聲明隊列
@Bean(EMAIL_QUEUE)
public Queue QUEUE_NEWS(){ //新聞的隊列
return new Queue(EMAIL_QUEUE);
}
//聲明交換機
@Bean(EXCHANGE_TOPIC_NAME)
public Exchange EXCHANGE_TOPIC_INFORM(){
//聲明瞭一個Topic類型的交換機,durable是持久化(重啓rabbitmq這個交換機不會被自動刪除)
return ExchangeBuilder.topicExchange(EXCHANGE_TOPIC_NAME).durable(true).build();
}
//聲明EMAIL_QUEUE隊列和交換機綁定關係,並且指定RoutingKey
@Bean
public Binding NEWS_BINDING_TOPIC(@Qualifier(EMAIL_QUEUE) Queue queue,
@Qualifier(EXCHANGE_TOPIC_NAME) Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with(QUEUE_BING_ROUTINGKEY).noargs();
}
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
3.消費監聽
EmailMessageListener類
package com.microservice.soa.listener;
import java.io.IOException;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microservice.soa.model.Email;
import com.microservice.soa.service.register.SendEmailService;
/**
* @RabbitListener 底層 使用Aop進行攔截,如果程序沒有拋出異常,自動提交事務,
* 如果Aop使用異常通知攔截 獲取異常信息的話,自動實現補償機制,該消息會緩存到rabbitmq服務器存放,
* 會一直重試到不拋出異常爲主。解決方式 修改重試機制策略 默認間隔5秒重試一次
*
*
*
* @ClassName: EmailMessageListener
* @Description: TODO(消息處理監聽類 郵件發送類)
* @author MAOJIAJIE
* @date 2019年4月12日
*
*/
@Component
public class EmailMessageListener{
private static Logger log = LoggerFactory.getLogger(EmailMessageListener.class);
@Resource
private SendEmailService sendEmailService;
@RabbitListener(queues = {"emailQueue"})
public void onMessage(Message message) {
// TODO Auto-generated method stub
log.info("*************************開始郵件監聽消息*************************");
String messageBody = new String(message.getBody());
ObjectMapper mapper = new ObjectMapper();
System.out.println(messageBody);
/**
* rabbitmq 默認情況下,如果消費者程序出現異常的情況下,會自動實現補償機制 (重試機制)
* 隊列服務器發送補嘗請求
*/
// int i = 1/0;
try {
Jackson2JsonMessageConverter jackson2JsonMessageConverter =new Jackson2JsonMessageConverter();
Email email = (Email)jackson2JsonMessageConverter.fromMessage(message);
// Email email = mapper.readValue(messageBody, Email.class);
log.info("接收到郵件消息:【" + email + "】");
//發送郵件通知
//EmailUtil.sendEmail(email);
sendEmailService.sendMessage(email);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
log.error("發送郵件失敗!:【" + e.toString() + "】");
}
}
}
4.接口請求類 RegisterAccess
package com.microservice.soa.access.register;
import java.util.Date;
import java.util.UUID;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.microservice.soa.api.register.RegisterServiceApi;
import com.microservice.soa.bean.email.EmailRequestBean;
import com.microservice.soa.bean.email.EmailResponseBean;
import com.microservice.soa.dao.user.UserDao;
import com.microservice.soa.model.Email;
import com.microservice.soa.model.User;
import com.microservice.soa.util.RespUtils;
import com.microservice.soa.util.UidUtils;
/**
*
* @ClassName: RegisterAccess
* @Description: TODO(郵件通知)
* @author MAOJIAJIE
* @date 2019年4月20日
*
*/
@RestController
public class RegisterAccess implements RegisterServiceApi {
private static Logger log = LoggerFactory.getLogger(RegisterAccess.class);
@Resource
private UserDao userDao;
@Resource
RabbitTemplate template;
@Override
@RequestMapping("sendEmail")
public EmailResponseBean sendMessage(EmailRequestBean emailRequestBean) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
Email email = new Email();
//發件人郵件地址
email.setFromAddress(emailRequestBean.getFromAddress());
//收件人郵件地址
email.setToAddress(emailRequestBean.getToAddress());
//郵件主題
email.setText("站點測試郵箱");
email.setContent("註冊成功!");
//入庫
User user = new User();
user.setUserId(UidUtils.createUtil());
user.setUserName(emailRequestBean.getUname());
user.setCreateTime(new Date());
user.setUserStart("01");
user.setOlineStart("01");
user.setUserEmail(emailRequestBean.getToAddress());
user.setUserPsw(emailRequestBean.getUpassword());
//插入表中
userDao.insert(user);
//測試註解事物
// System.out.println(1 / 0);
try {
//發送到消息隊列中
// template.convertAndSend(email);
//指定交換機,指定routing key,發送消息的內容
template.convertAndSend("testChange","email.bar.test",email);
log.info("****************用戶註冊成功!");
} catch (Exception e) {
// TODO Auto-generated catch block
//e.printStackTrace();
log.info("用戶註冊失敗:原因【"+e.toString()+"】");
return RespUtils.createBaseResp("1004", "用戶註冊失敗:原因【"+e.toString()+"】", email.getToAddress());
}
return RespUtils.createBaseResp("000", "測試成功!", email.getToAddress());
}
}
6. 測試
項目下載地址: