工作中用到的RabbitMQ例子 , 但是最后没有用 , 用的CMQ , 顺便说下CMQ社区真的少 , 并且功能少 .

一、消息体

package com.bootdo.common.rabbitmq.batchsendsms;

import com.alibaba.fastjson.JSON;
import com.bootdo.common.utils.UUIDGenerator; import java.io.Serializable;
import java.util.Date;
import java.util.Map; /**
* MQ消息体
* @author yuduojia
* @date 2018/8/1 10:42
*/
public class BacthSendSMSMessage implements Serializable{
private static final long serialVersionUID = 1L; private Integer intRun;//当前次数
private Integer total;//总次数
private String productCode; // 生产者代码
private String consumerCode; // 消费者代码
private String messageId; // 消息唯一标识
private Date created; // 消息发送时间
private Map<String, Object> bussinessBody; // 消息体,封装业务数据 private BacthSendSMSMessage() {
super();
} public BacthSendSMSMessage(Integer intRun, Integer total, String productCode, String consumerCode, Map<String, Object> bussinessBody) {
this.intRun = intRun;
this.total = total;
this.productCode = productCode;
this.consumerCode = consumerCode;
this.bussinessBody = bussinessBody;
} public static String productMQMessage(Integer intRun, Integer total, String productCode, String consumerCode, Map<String, Object> bussinessBody) {
BacthSendSMSMessage mqObj = new BacthSendSMSMessage(intRun, total, productCode, consumerCode, bussinessBody);
mqObj.setCreated(new Date());
mqObj.setMessageId(generatSeriaeNo());
return JSON.toJSONString(mqObj);
} //生成消息唯一标识
private static String generatSeriaeNo() {
return UUIDGenerator.generate();
} public String getProductCode() {
return productCode;
} public void setProductCode(String productCode) {
this.productCode = productCode;
} public String getConsumerCode() {
return consumerCode;
} public void setConsumerCode(String consumerCode) {
this.consumerCode = consumerCode;
} public String getMessageId() {
return messageId;
} public void setMessageId(String messageId) {
this.messageId = messageId;
} public Date getCreated() {
return created;
} public void setCreated(Date created) {
this.created = created;
} public Map<String, Object> getBussinessBody() {
return bussinessBody;
} public void setBussinessBody(Map<String, Object> bussinessBody) {
this.bussinessBody = bussinessBody;
} public static long getSerialVersionUID() {
return serialVersionUID;
} public Integer getIntRun() {
return intRun;
} public void setIntRun(Integer intRun) {
this.intRun = intRun;
} public Integer getTotal() {
return total;
} public void setTotal(Integer total) {
this.total = total;
} @Override
public String toString() {
return "BacthSendSMSMessage{" +
"intRun=" + intRun +
", total=" + total +
", productCode=" + productCode +
", consumerCode=" + consumerCode +
", messageId='" + messageId + '\'' +
", created=" + created +
", bussinessBody=" + bussinessBody +
'}';
}
}

二、发布者

package com.bootdo.common.rabbitmq.batchsendsms;

import com.bootdo.server.vo.SendModel;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.List;
import java.util.Map;
import java.util.UUID; @Component
public class BatchSendSMSSender {
private static final Logger logger = LoggerFactory.getLogger(BatchSendSMSSender.class);
@Autowired
private RabbitTemplate rabbitTemplate; public void send(List<SendModel> list, String channel) {
int count = 0;
for (int i = 0; i < list.size(); i++) {
Map<String, Object> bussiness = Maps.newHashMap();
bussiness.put("productId", 15);
bussiness.put("companyId", 100); //B公司id
bussiness.put("isSmallPerson", 1); //1 or 0
bussiness.put("assignType", 1);
bussiness.put("bookNum", 1);
bussiness.put("bookAmount", 100);
bussiness.put("channel",channel);
bussiness.put("templeteCode",list.get(i).getTempleteCode());
bussiness.put("templeteParam",list.get(i).getTempleteParam());
bussiness.put("phone",list.get(i).getPhone()); String msgId = UUID.randomUUID().toString(); String messageBody = BacthSendSMSMessage.productMQMessage(i+1,list.size(),"pro","pro",bussiness);
Message message = MessageBuilder.withBody(messageBody.getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setCorrelationIdString(msgId).build();
/*将 msgId和 CorrelationData绑定*/
CorrelationData correlationData = new CorrelationData(msgId); rabbitTemplate.convertAndSend("exchange", "ttd.trust.product", message);
System.out.println("ProductTopicSender : " + messageBody);
}
} }

三、订阅者(监听)

package com.bootdo.common.rabbitmq.batchsendsms;

import com.alibaba.fastjson.JSON;

import com.bootdo.common.config.ConfigConstants;
import com.bootdo.server.service.SMSRetryProxy;
import com.bootdo.server.service.SMSService;
import com.bootdo.server.service.SMSToSend;
import com.bootdo.sms.domain.ModelDO;
import com.bootdo.sms.domain.SmsSendLogDO;
import com.bootdo.sms.service.ModelService;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* MQ消息监听
* @author yuduojia
* @date 2018/7/30 14:53
*/
@Component
@RabbitListener(queues = "ttd.trust.product")
public class BctchSendSMSReceiver {
private final Logger logger = LoggerFactory.getLogger(BctchSendSMSReceiver.class);
@Autowired
private ModelService modelService;
@Autowired
private ConnectionFactory connectionff; @Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionff);
container.setQueueNames("ttd.trust.product");
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(1);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception { try {
logger.info("消费端接收到消息:" + message.getMessageProperties() + ":" + new String(message.getBody()));
logger.info("topic:"+message.getMessageProperties().getReceivedRoutingKey());
byte[] body = message.getBody();
String jsonString = new String(body);
logger.info("BctchSendSMSReceiver : " + jsonString);
BacthSendSMSMessage msg = JSON.parseObject(jsonString, BacthSendSMSMessage.class);
Map<String, Object> bussinessBody = msg.getBussinessBody();
List<String> templateParams = (List<String>)bussinessBody.get("templeteParam");
String phone = (String) bussinessBody.get("phone"); ModelDO modelDO = modelService.getbyCode((String)bussinessBody.get("templeteCode"));
String text = modelDO.getSendModel();
String[] split = text.split("#");
String model = "";
for (int i = 0; i < split.length; i++) {
if(i%2==0){
model = model + split[i];
}
else if(i%2!=0){
model = model + templateParams.get((i-1)/2);
}
}
SMSToSend toDo = new SMSRetryProxy().getInstance(new SMSService());
Map<String,Object> map = new HashMap<String,Object>();
map.put("channel",(String) bussinessBody.get("channel"));
map.put("sendTemplateCode",(String)bussinessBody.get("templeteCode"));
map.put("templeteContents",templateParams);
map.put("mobile",phone);
map.put("apikey", ConfigConstants.SEND_SMS_APIKEY2);
// map.put("text","【娄维伟】尊敬的张帅东,您有一个工单号为:222991011111111111的待处理工单,请您及时处理!");
map.put("text",model);
map.put("smsProvider","云片");
Map<String,Object> return1 = toDo.singleSend(map);
logger.info("SendSMSController——sendSMS——短信发送详细信息为:"+return1.toString());
SmsSendLogDO smsSendLogDO = (SmsSendLogDO)return1.get("smsSendLogDO"); boolean preRet = preEventHandler(msg);
if (preRet == false) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费一条
return ;
} boolean postRet = postEventHandler(msg);
if (postRet == false) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费一条
return ;
}
//记录日志
afterEventHandler(msg);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费一条
//channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
e.printStackTrace();
if (message.getMessageProperties().getRedelivered()) {
logger.error("消息已重复处理失败,拒绝再次接收__"+message.getMessageProperties().getDeliveryTag());
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); // 拒绝消息
} else {
logger.error("消息即将再次返回队列处理__"+message.getMessageProperties().getDeliveryTag());
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true); // requeue为是否重新回到队列
}
}
}
});
return container;
} private void recordLogMQ(BacthSendSMSMessage message, Integer state) {
/*LogMqMessage log = new LogMqMessage();
log.setMessageId(message.getMessageId());
log.setProductCode(message.getProductCode());
log.setConsumerCode(message.getConsumerCode());
log.setEvent(message.getEvent());
log.setBussinessBody(JSON.toJSONString(message));
log.setState(state); logMqMessageService.insertEntry(log);*/
System.out.println("记录日志");
} /**
* 消息体检查
* @param message
* @return Map
*/
private boolean preEventHandler(BacthSendSMSMessage message) { return false;
} /**
* 业务处理
* @param message
* @return
*/
private boolean postEventHandler(BacthSendSMSMessage message) { return true;
} /**
* 记录消息日志
* @param message
*/
private void afterEventHandler(BacthSendSMSMessage message) {
recordLogMQ(message, 1);
} }

四、RabbitMQConfig

package com.bootdo.common.rabbitmq.batchsendsms.config;

import com.bootdo.common.rabbitmq.confirm.MsgSendConfirmCallBack;
import com.bootdo.common.rabbitmq.confirm.MsgSendReturnCallback;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* @author yuduojia
* @date 2018/8/3 15:14
*/
@Configuration
public class RabbitMqConfig { public static final String ROUTING_KEY_1 = "batch_send_key1";
public static final String ROUTING_KEY_2 = "batch_send_key2"; @Autowired
private QueueConfig queueConfig; @Autowired
private ExchangeConfig exchangeConfig; @Autowired
private ConnectionFactory connectionFactory; /**
* 将消息队列1和交换机1进行绑定,指定队列key1
*/
@Bean
public Binding binding_one() {
return BindingBuilder.bind(queueConfig.firstQueue()).to(exchangeConfig.directExchange()).with(RabbitMqConfig.ROUTING_KEY_1);
} /**
* 将消息队列2和交换机1进行绑定,指定队列key2
*/
@Bean
public Binding binding_two() {
return BindingBuilder.bind(queueConfig.secondQueue()).to(exchangeConfig.directExchange()).with(RabbitMqConfig.ROUTING_KEY_2);
} /**
* 定义rabbit template用于数据的接收和发送
* 可以设置消息确认机制和回调
* @return
*/
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
// template.setMessageConverter(); 可以自定义消息转换器 默认使用的JDK的,所以消息对象需要实现Serializable
// template.setMessageConverter(new Jackson2JsonMessageConverter()); template.setConfirmCallback(msgSendConfirmCallBack());
template.setReturnCallback(msgSendReturnCallback());
template.setMandatory(true);
return template;
} @Bean
public MsgSendConfirmCallBack msgSendConfirmCallBack(){
return new MsgSendConfirmCallBack();
} @Bean
public MsgSendReturnCallback msgSendReturnCallback(){
return new MsgSendReturnCallback();
} }

五、QueueConfig

package com.bootdo.common.rabbitmq.batchsendsms.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.HashMap;
import java.util.Map; /**
* 队列配置 可以配置多个队列
* @author zhuzhe
* @date 2018/5/25 13:25
* @email 1529949535@qq.com
*/
@Configuration
public class QueueConfig { /*对列名称*/
public static final String BATCH_SEND_QUEUE_NAME1 = "batch_send_queue1";
public static final String BATCH_SEND_QUEUE_NAME2 = "batch_send_queue2";
//public static final String BATCH_SEND_QUEUE_NAME3 = "batch_send_queue3"; @Bean
public Queue firstQueue() {
return new Queue(BATCH_SEND_QUEUE_NAME1,true,false,false);
} @Bean
public Queue secondQueue() {
return new Queue(BATCH_SEND_QUEUE_NAME2,true,false,false);
} /*@Bean
public Queue thirdQueue() {
return new Queue(BATCH_SEND_QUEUE_NAME3,true,false,false);
}*/
}

六、ExchangeConfig

package com.bootdo.common.rabbitmq.batchsendsms.config;

import org.springframework.amqp.core.DirectExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* 消息交换机配置 可以配置多个
* @author zhuzhe
* @date 2018/5/25 15:40
* @email 1529949535@qq.com
*/
@Configuration
public class ExchangeConfig { public final String EXCHANGE_01 = "batch_send_exchange"; @Bean
public DirectExchange directExchange(){
DirectExchange directExchange = new DirectExchange(EXCHANGE_01,true,false);
return directExchange;
}
}

七、确认后回调

package com.bootdo.common.rabbitmq.confirm;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData; /**
* 确认后回调 massage2exchange
* @author yuduojia
* @date 2018/8/2 15:49
*/
public class MsgSendConfirmCallBack implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
System.out.println("消息确认成功cause:"+cause);
} else {
//处理丢失的消息
System.out.println("消息确认失败:"+correlationData.getId()+"#cause:"+cause);
}
}
}

八、失败后回调

package com.bootdo.common.rabbitmq.confirm;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate; /**
* 失败后return回调 exchange2queue
* @author yuduojia
* @date 2018/8/2 15:48
*/
public class MsgSendReturnCallback implements RabbitTemplate.ReturnCallback {
@Override
public void returnedMessage(Message message, int replyCode, String replyText,
String exchange, String routingKey) {
System.out.println("确认后回调return--message:" + new String(message.getBody()) + ",replyCode:" + replyCode + ",replyText:"
+ replyText + ",exchange:" + exchange + ",routingKey:" + routingKey);
}
}

如果实际用需要优化 , 我这个没有优化就被砍掉啦 , 很遗憾 等下次用到再更新,确认回调机制 用redis做就可以。

  如果有疑问或者建议欢迎评论。

Redis进阶例子的更多相关文章

  1. Redis进阶实践之十八 使用管道模式加速Redis查询

    一.引言             学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中批量的增加数据,肯定是大批量的,为了这主题,我从新找起了解决方案.目前 ...

  2. Redis进阶实践之四Redis的基本数据类型(转载4)

    Redis进阶实践之四Redis的基本数据类型 一.引言 今天正式开始了Redis的学习,如果要想学好Redis,必须先学好Redis的数据类型.Redis为什么会比以前的Memchaed等内存缓存软 ...

  3. Redis进阶实践之十八 使用管道模式提高Redis查询的速度

    原文:Redis进阶实践之十八 使用管道模式提高Redis查询的速度 一.引言             学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中 ...

  4. Redis进阶实践之十三 Redis的Redis-trib.rb文件详解

    一.简介     事先说明一下,本篇文章不涉及对redis-trib.rb源代码的分析,只是从使用的角度来阐述一下,对第一次使用的人来说很重要.redis-trib.rb是redis官方推出的管理re ...

  5. Redis进阶实践之十六 Redis大批量增加数据

    一.介绍      有时,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键.这就是所谓的批量插入,本文档的目标是提供有关如何以尽可能快的速度向Redis提 ...

  6. Redis进阶实践之十三 Redis的Redis-trib.rb脚本文件使用详解

    转载来源:http://www.cnblogs.com/PatrickLiu/p/8484784.html 一.简介 事先说明一下,本篇文章不涉及对redis-trib.rb源代码的分析,只是从使用的 ...

  7. Redis进阶实践之九 独立封装的RedisClient客户端工具类(转载9)

    Redis进阶实践之九 独立封装的RedisClient客户端工具类 一.引言 今天开始有关Redis学习的第九篇文章了,以后肯定会大量系统使用Redis作为缓存介质,为了更好的更好的Redis,自己 ...

  8. Redis进阶实践之七Redis和Lua初步整合使用(转载 7)

    Redis进阶实践之七Redis和Lua初步整合使用 一.引言 Redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运 ...

  9. Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务(转载6)

    Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务 一.引言 今天本来没有打算写这篇文章,但是,今天测试Redis的时候发现了两个问题 ...

随机推荐

  1. sql常识性误解

    今天在公司一个项目,遇到一个问题,最后解决下来竟然发现自己对sql竟然存在一个常识性的误解 表数据 需求如下 查找 name中的数据被参数 'adsb' 包含的的列 个人原先的误区一直在于一个认识, ...

  2. ASP.NET Core Web API + Angular 仿B站(二)后台模型创建以及数据库的初始化

    前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...

  3. E20170426-gg

    recursive   adj. 回归的,递归的; removal    n. 除去; 搬迁; 免职; 移走; customize vt. 定制,定做; 按规格改制;

  4. 解决sqlserver的sql脚本内存不足问题

    1.Win+R输出cmd 2.sqlcmd -i  E:\Work\xxxxx.sql -d xxxxx(数据库名称) -s 127.0.0.1

  5. hdoj1106

    果然...这种一条字符串的处理,还是不熟练,居然wa了四次--. 预处理预处理!!!!: 然后中间对条件的确定,标记的改变+预处理,不够严谨啊!!! #include<cstdio> #i ...

  6. Visual Studio 的Build Event 使用

    rmdir Configuration mkdir Configuration Copy "$(ProjectDir)Configuration\Spec.config" &quo ...

  7. 9-25模拟赛 By cellur925

    1.相遇(railway.cpp/c/pas)时间限制:1s内存限制:256MB[问题描述]已知我国有 n 座城市,这些城市通过 n-1 条高铁相连.且任意两个城市联通.小 A 想从 x1 号城市出发 ...

  8. 洛谷 P1339 [USACO09OCT]热浪Heat Wave

    题目链接:https://www.luogu.org/problemnew/show/P1339 解题思路: 一道简单的最短路水题,dijkstra解法模板思路:https://www.cnblogs ...

  9. java 丢失的异常

    采用finally从句中的,可能会丢失异常 package thinking; //: LostMessage.java // How an exception can be lost class V ...

  10. android 浏览器对图片加载高度渲染问题

    今天在开发有道汉语词典移动版的时候遇到了一个很奇怪的问题. 在android设备上访问的时候,总是发现有底部背景色不能完全渲染出来的情况(有时候又是正常的,一会儿出现一会儿不出现,iphone设备也是 ...