1、所需jar包下载
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.1</version>
</dependency>
2、spring bean配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd">
<!--创建连接工厂-->
<amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://localhost:61616" userName="admin" password="admin"/>
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory" />
<!-- Session缓存数量 -->
</bean>
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="admin"/>
<property name="password" value="admin"/>
</bean>
<!-- 定义JmsTemplate的Queue类型 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<constructor-arg ref="connectionFactory" />
<!-- 非pub/sub模型(发布/订阅),即队列模式 -->
<property name="pubSubDomain" value="false" />
</bean>
<!-- 定义Queue监听器 -->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="queue" ref="consumerMessageListener"/>
</jms:listener-container>
<!--这个是队列目的地,点对点的 -->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>queue</value>
</constructor-arg>
</bean>
<!--消费者监听器-->
<bean id="consumerMessageListener" class="com.ycst.craft4j.system.listener.ConsumerMessageListener">
<property name="destination" ref="queueDestination"/>
</bean>
</beans>
【应用场景】有货主下单后,需要根据优先级给司机派单,如果司机不接单,10分钟后就要继续派单给下一个司机,如此循环最多三次。
消费者监听器
package com.ycst.craft4j.system.listener;
import java.sql.Timestamp;
import java.util.List;
import javax.annotation.Resource;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ycst.craft4j.constants.Constants;
import com.ycst.craft4j.core.entity.LocationCity;
import com.ycst.craft4j.core.entity.OrderSupplier;
import com.ycst.craft4j.core.entity.Suppliers;
import com.ycst.craft4j.core.entity.TransportOrder;
import com.ycst.craft4j.core.mapper.CodeMstMapper;
import com.ycst.craft4j.core.mapper.OrderDistributeMapper;
import com.ycst.craft4j.core.mapper.OrderSupplierMapper;
import com.ycst.craft4j.core.mapper.SupplierLinesMapper;
import com.ycst.craft4j.core.mapper.SuppliersMapper;
import com.ycst.craft4j.core.mapper.TransportOrderMapper;
import com.ycst.craft4j.system.util.DateUtil;
public class ConsumerMessageListener implements MessageListener{
@Resource
@Qualifier("queueDestination")
private Destination destination;
@Resource
private JmsTemplate jmsTemplate;
@Resource
private TransportOrderMapper orderDao;
@Resource
private SupplierLinesMapper linesDao;
@Resource
private OrderDistributeMapper orderDistributeDao;
@Resource
private CodeMstMapper codeMstDao;
@Resource
private SuppliersMapper supplierDao;
@Resource
private OrderSupplierMapper orderSupplierDao;
@Override
@Async
@Transactional
public void onMessage(Message message){
Thread thread = new Thread();
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}finally {
thread.interrupt();
}
//这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换
String data = null;
try {
data = (String)message.getObjectProperty("data");
} catch (JMSException e) {
e.printStackTrace();
}
JSONObject object = JSON.parseObject(data);
//接收到消息,判断订单供应商是否接单,返回回复消息,再进行判断是否需要重新派车
int orderId = object.getIntValue("orderId");
TransportOrder order = orderDao.queryOrderById(orderId);
int count = orderSupplierDao.countDistributeNum(orderId);
int receiveOrder = orderSupplierDao.getOrderDistributeFlg(orderId);
//失效,重新分配
LocationCity fromCity = order.getFromCity();
LocationCity toCity = order.getToCity();
List<Integer> supplierIdList = linesDao.getFitSupplierList(fromCity == null ? 0 : fromCity.getId()
,toCity == null ? 0 : toCity.getId());
//获取已经失效的供应商
List<Integer> distributingSupplierList = orderSupplierDao.getDistributingSupplier(orderId);
List<Integer> invalidSupplierList = orderSupplierDao.getInvalidSupplierList(orderId
,Constants.SUPPLY_ORDER_STATUS.INVALID
,Constants.SUPPLY_ORDER_STATUS.CANCLE);
//把无效的订单更改为已失效
for(Integer orderSupplierId : distributingSupplierList){
orderSupplierDao.updateOrderSupplier(orderId, orderSupplierId, Constants.SUPPLY_ORDER_STATUS.INVALID);
}
supplierIdList.removeAll(invalidSupplierList);
supplierIdList.removeAll(distributingSupplierList);
//派单超过3或者已经派单了
if(count >= 3 || receiveOrder != 0 || supplierIdList.size() == 0){
thread.interrupt();
return;
}else{
//继续派单
if((supplierIdList != null)&&(supplierIdList.size() != 0)){
final Suppliers suppliers = supplierDao.getFitSupplier(supplierIdList);
if(suppliers == null){
thread.interrupt();
return;
}
//派单,发送消息队列
final OrderSupplier supplier = new OrderSupplier();
supplier.setTransportOrder(order);
//CodeMst codeMst = codeMstDao.selectByCode(Constants.SUPPLY_ORDER_STATUS.NEW_ORDER);
supplier.setUstatus(null);
supplier.setSupplier(suppliers);
Timestamp now = DateUtil.getNowTimestamp();
Timestamp after = new Timestamp(now.getTime()+10*60*1000);
supplier.setExpireTime(after);
int ret = orderSupplierDao.addOrderSuppliers(supplier);
final String orderNo = order.getOrderNo();
final int oId = order.getId();
if(ret == 1){
thread.interrupt();
//发送消息队列
jmsTemplate.send(destination, new MessageCreator(){
@Override
public Message createMessage(Session session) throws JMSException {
MessageProducer producer = session.createProducer(destination);
String data = "{orderNo:"+orderNo+",orderId:"+oId+",supplierId:"+supplier.getId()+"}";
ObjectMessage objectMessage = session.createObjectMessage();
objectMessage.setObjectProperty("data", data);
long time = 10*60*1000;
//objectMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
//producer.send(objectMessage);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
return objectMessage;
}
});
}
}
}
}
public Destination getDestination() {
return destination;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
}
派单
前面的业务逻辑忽略,第一次生产消息,派单给司机(消息被消费了),接下来监听器会使用线程延迟10分钟,继续生产消息
//发送消息队列
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
MessageProducer producer = session.createProducer(destination);
String data = "{orderNo:"+orderNo+",orderId:"+oId+",supplierId:"+suppliers.getId()+"}";
ObjectMessage objectMessage = session.createObjectMessage();
objectMessage.setObjectProperty("data", data);
long time = 10*60 * 1000;
//objectMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
//producer.send(objectMessage);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
return objectMessage;
}
});