工作中用到的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. pythonchallenge 2

     pythonchallenge是一个很有意思的学习python的网站,通过用程序解开一个谜,可以进入到下一个level,总共有几十个level,网址是http://www.pythonchallen ...

  2. ARC和MRC混合使用

    在一些项目中尤其是做迭代的项目经常会出现MRC的项目,但是我们习惯了ARC环境,反之也是一样.这是我们不必去修改代码去掉release之类的,按照如下方案去做就可以了. 项目 -> Build ...

  3. 704. Binary Search

    Given a sorted (in ascending order) integer array nums of n elements and a target value, write a fun ...

  4. python 生成器 generator

    一.生成器定义 通过列表生成表达式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢? ...

  5. mysqldump 工具使用详解——参数选项

    mysqldump 简介 mysqldump 是一种用于逻辑备份的客户端工具,它会产生一套能够重新构建数据库或表的SQL语句.所谓逻辑备份:是利用SQL语言从数据库中抽取数据并存于二进制文件的过程.逻 ...

  6. SAE上无法加载css等文件

    如果你的SAE用到了这些文件,你会发现本地虽然能够运行成功,但是SAE上却无法加载. 其实就是地址发生了变化,我们告诉SAE这些东西怎么找就可以了. 例如我的css和js文件放在了app/static ...

  7. 题解报告:hdu 1969 Pie(二分)

    Problem Description My birthday is coming up and traditionally I'm serving pie. Not just one pie, no ...

  8. synchronized(6)修饰语方法之:static方法

    当一个synchronized关键字修饰的方法同时又被static修饰,之前说过,非静态的同步方法会将对象上锁,但是静态方法不属于对象,而是属于类,它会将这个方法所在的类的Class对象上锁. 一个类 ...

  9. Suricata的总体架构

    Suricata的总体架构  报文检测系统通常四大部分,报文获取.报文解码.报文检测.日志记录:suricata不同的功能安装模块划分,一个模块的输出是另一个模块的输入,suricata通过线程将模块 ...

  10. 初学.net增删改查

    分页显示 DAL: public List GetListByPager(int PageIndex, int PageSize, out int RowCount) { string sql = & ...