登录http://localhost:15672/#/queues guest/guest
添加交换机
添加队列,并绑定交换机
rabbitmq:
addresses: 192.168.1.1:5672
username: guest
password: jingzhiadmin
virtual-host: /
publisher-confirms: true #confirm模式
publisher-returns: true #return机制
template:
mandatory: true #与return机制结合配置次属性
connection-timeout: 5000
listener:
simple:
prefetch: 5 #定义消费者同时处理5个消息
acknowledge: manual #消息手动确认
package com.jzlife.management.rabbitmq;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.SerializerMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
public class RabbitMqConfig {
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// factory.setMessageConverter(new Jackson2JsonMessageConverter());
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return factory;
}
// @Bean
// @Scope("prototype")
// public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
// RabbitTemplate template = new RabbitTemplate(connectionFactory);
// template.setMandatory(true);
// template.setMessageConverter(new SerializerMessageConverter());
// return template;
//
// }
/**
* 如果消息没有到exchange,则confirm回调,ack=false
*
* 如果消息到达exchange,则confirm回调,ack=true
*
* exchange到queue成功,则不回调return
*
* exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
*/
}
发送到mq
package com.jzlife.management.rabbitmq;
import com.jzlife.management.constant.MqConstant;
import com.jzlife.management.entity.mq.MqRecord;
import com.jzlife.management.entity.mq.OrderApplyMessage;
import com.jzlife.management.service.MqRecordService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
@Component
public class TestOrderApplySender {
private Logger logger = LogManager.getLogger(getClass());
@Autowired
RabbitTemplate rabbitTemplate;
/**
* 生产message
*
* @param messge
*/
public void sendMessage(Integer i) {
// // 设置发送后的返回调用
// rabbitTemplate.setConfirmCallback(confirmCallback);
//
// // 发送前的业务处理
// CorrelationData correlationData = new CorrelationData();
// correlationData.setId(orderApplyMessage.getMessageId());
// rabbitTemplate.convertAndSend(MqConstant.QUEUES_ORDER_APPLY, orderApplyMessage, correlationData);
Map<String,Object> objMapData=new HashMap<String, Object>();
objMapData.put("aa", i);
System.out.println("fasongle------------1");
rabbitTemplate.convertAndSend("exchange-test", null, objMapData);
System.out.println("fasongle------------");
}
// final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
// @Override
// public void confirm(CorrelationData correlationData, boolean ack, String cause) {
// logger.info("confirmCallback correlationData:" + correlationData);
// String correlationId = correlationData.getId();// 消息id
//
// System.out.println("ack"+ack);
// }
//
// };
}
接受fanout模式
package com.jzlife.management.rabbitmq;
import com.jzlife.management.aop.PlatAuth;
import com.jzlife.management.constant.MqConstant;
import com.rabbitmq.client.Channel;
import java.util.Map;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
/**
* @author fuxubing
*/
@Component
public class TestOrderApplyListener {
/**
* 消费message exchange = @Exchange(value = "order-exchange", durable = "true",
* type = "topic", ignoreDeclarationExceptions = "true")
*
* @param message
* @param channel
* @throws Exception
*/
// @RabbitListener(queues = MqConstant.QUEUES_ORDER_APPLY)
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "queue-exchange-test"), exchange = @Exchange(value = "exchange-test", type = "fanout")
))
@RabbitHandler
public void onMessage2(@SuppressWarnings("rawtypes") Message message, @Payload Map data, Channel channel,
@Headers Map<String, String> headers) throws Exception {
Thread.sleep(10);
System.out.println(data);
Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
channel.basicAck(deliveryTag, false);
}
}
另外情况 使用默认的交换机,也就是队列没有强制绑定交换机,发起时用的队列名
package com.jzlife.management.rabbitmq;
import com.jzlife.management.constant.MqConstant;
import com.jzlife.management.entity.mq.MqRecord;
import com.jzlife.management.entity.mq.OrderApplyMessage;
import com.jzlife.management.service.MqRecordService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
@Component
public class OrderApplySender {
private Logger logger = LogManager.getLogger(getClass());
@Autowired
RabbitTemplate rabbitTemplate;
@Autowired
MqRecordService mqRecordService;
/**
* 生产message
*
* @param messge
*/
public void sendMessage(OrderApplyMessage orderApplyMessage) {
// 设置发送后的返回调用
rabbitTemplate.setConfirmCallback(confirmCallback);
// 发送前的业务处理
CorrelationData correlationData = new CorrelationData();
correlationData.setId(orderApplyMessage.getMessageId());
rabbitTemplate.convertAndSend(MqConstant.QUEUES_ORDER_APPLY, orderApplyMessage, correlationData);
}
final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
logger.info("confirmCallback correlationData:" + correlationData);
String correlationId = correlationData.getId();// 消息id
MqRecord record =mqRecordService.selectByCorrelationId(correlationId);
if (ack) {
// 发送成功 ,把消息订单状态改为2,说明消息发送成功了
record.setStatus(MqConstant.QUEUES_STATUS_LINEUP);
} else {
//失败情况
if(record.getFailurePostNumber().equals(2)) {//失败次数2(加首次)也就发了3次就结束
record.setStatus(MqConstant.QUEUES_STATUS_FAIL);//失败
record.setFailReason("发送至消息队列失败");
}else {
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.SECOND, 30); //30秒
record.setFailurePostTime(nowTime.getTime());//下次发送时间
}
}
mqRecordService.updateBycorrelationId(record);
}
};
}
package com.jzlife.management.rabbitmq;
import com.jzlife.management.constant.MqConstant;
import com.jzlife.management.constant.NoticeActionEnum;
import com.jzlife.management.entity.InvenCalcul.DateTimeServiceItemInfo;
import com.jzlife.management.entity.InvenCalcul.TimeServiceItemInfo;
import com.jzlife.management.entity.mq.MqRecord;
import com.jzlife.management.entity.mq.OrderApplyMessage;
import com.jzlife.management.entity.mq.OrderServiceTime;
import com.jzlife.management.notice.NoticeExecutor;
import com.jzlife.management.service.InventoryCalculationService;
import com.jzlife.management.service.MqRecordService;
import com.jzlife.management.service.OrderApplyService;
import com.jzlife.management.service.UnitCommodityService;
import com.jzlife.management.util.JsonUtil;
import com.jzlife.management.util.ResponseUtil;
import com.jzlife.management.utils.OrderUtil;
import com.jzlife.management.vo.SelectStockAndWorkerId;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 11
*/
@Component
public class OrderApplyListener {
// @Resource
// private OrderService orderService;
@Autowired
OrderApplyService orderApplyService;
@Resource
private InventoryCalculationService inventoryCalculationService;
@Resource
private UnitCommodityService unitCommodityService;
@Autowired
MqRecordService mqRecordService;
@Autowired
private NoticeExecutor noticeExecutor;
private static final Logger logger = LoggerFactory.getLogger(OrderApplyListener.class);
/**
* 消费message exchange = @Exchange(value = "order-exchange", durable = "true",
* type = "topic", ignoreDeclarationExceptions = "true")
*
* @param message
* @param channel
* @throws Exception
*/
@RabbitListener(queues = MqConstant.QUEUES_ORDER_APPLY)
@RabbitHandler
public void onMessage2(@SuppressWarnings("rawtypes") Message message, Channel channel) throws Exception {
logger.info("消费端22222Payload: " + JsonUtil.getJson(message.getPayload()));
Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
channel.basicAck(deliveryTag, false);// 手签\
/**
* 若ack失败 程序断开于rabbitmq的链接后 unacked的消息状态会重新变为ready 等待消费。
* 代码更新后,server应用连接rabbitmq 就会重新消费掉消息。
*/
// 业务处理
OrderApplyMessage orderApplyMessage = JsonUtil.getEntity(message.getPayload(), OrderApplyMessage.class);
if (null == orderApplyMessage) {
messageStatus(message, channel, null, MqConstant.ORDER_STATUS_FAIL, "下单数据异常空值");
}
assert orderApplyMessage != null;
// 判断库存
Map<String, Object> map = unitCommodityService.selectByCommodityNo(orderApplyMessage.getUnitCommodityNo());
if (map == null) {
messageStatus(message, channel, null, MqConstant.ORDER_STATUS_FAIL, "商品不存在");
return;
}
Long unitCommdId = (Long) map.get("id");
List<OrderServiceTime> orderServiceTimeList = orderApplyMessage.getOrderServiceTimeList();
SelectStockAndWorkerId selectStockAndWorkerId = OrderUtil.setStockParams(unitCommdId, orderServiceTimeList);
List<DateTimeServiceItemInfo> itemInfos = inventoryCalculationService
.selectWorkerToService(selectStockAndWorkerId);
if (itemInfos.isEmpty()) {
messageStatus(message, channel, null, MqConstant.ORDER_STATUS_FAIL, "库存数不足");
return;
}
for (DateTimeServiceItemInfo itemInfo : itemInfos) {
for (TimeServiceItemInfo timeServiceItemInfo : itemInfo.getTimeList()) {
Integer stockNumber = timeServiceItemInfo.getStockNumber();
if (stockNumber <= 0) {
messageStatus(message, channel, null, MqConstant.ORDER_STATUS_FAIL, "库存数不足");
return;
}
}
}
// 下订单
String orderNo = null;
Object object;
Map<String, Object> map1 = new HashMap<>(16);
map1.put("action", NoticeActionEnum.ORDER_SUCCESS);
try {
orderNo = orderApplyService.createOrder(orderApplyMessage, itemInfos);
messageStatus(message, channel, orderNo, MqConstant.ORDER_STATUS_OK, null);
map1.put("orderNo", orderNo);
object = ResponseUtil.ok(map1);
} catch (Exception e) {
e.printStackTrace();
messageStatus(message, channel, null, MqConstant.ORDER_STATUS_FAIL, "下单异常|" + getErrorMsg(e));
object = ResponseUtil.fail(map1);
}
noticeExecutor.sendNotice(object, orderApplyMessage.getNoticeUrl());
}
/**
* 处理消息状态
*
* @param message
* @param channel
* @param orderNo
* @param orderStatus
* @param failReason
* @throws IOException
*/
private void messageStatus(@SuppressWarnings("rawtypes") Message message, Channel channel, String orderNo,
Integer orderStatus, String failReason) throws IOException {
OrderApplyMessage orderApplyMessage = JsonUtil.getEntity(message.getPayload(), OrderApplyMessage.class);
MqRecord mqRecord = new MqRecord();
mqRecord.setCorrelationId(orderApplyMessage == null ? null : orderApplyMessage.getMessageId());
mqRecord.setOrderNo(orderNo);
mqRecord.setOrderStatus(orderStatus);
mqRecord.setFailReason(failReason);
mqRecordService.updateBycorrelationId(mqRecord);
}
}