一、生产者和消费者
rabbitmq主要就是消息的生产和消息的消费,生产者将消息发送到队列中,消费者监听队列,一有消息就立马进行消费。
因此需要生产者和消费者类,分别如下:
1、生产者类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
public class Cls2SalesMqSender {
private final Logger logger = LoggerFactory.getLogger(Cls2SalesMqSender.class);
@Autowired
private RabbitTemplate rabbitTemplate;
// 交换机名称
private String exchangeName;
// 路由键
private String routingKey;
/**
*发送消息方法,msg为要发送的消息
*/
public void sendMessage(String msg) {
try {
logger.info("发送信息开始");
// 发送信息
rabbitTemplate.convertAndSend(exchangeName, routingKey, msg, messagePostProcessor);
logger.info("发送信息结束");
} catch (Exception e) {
logger.error("cif发送消息体到dps失败:", e);
}
}
// 省略setter/getter方法
}
2、消费者类
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import java.nio.charset.StandardCharsets;
@Service("repaymentSuccessMessageListener")
public class RepaymentSuccessMessageListener implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(RepaymentSuccessMessageListener.class);
/**
* 消息消费者,只要监听到消息就进行消费处理
*
* @param message 监听到的消息
*/
@Override
public void onMessage(Message message) {
logger.info("RepaymentSuccessMessageListener.onMessage() begin... message=" + JSON.toJSONString(message));
try {
String messageStr = new String(message.getBody(), StandardCharsets.UTF_8);
logger.info("监听到的message=" + messageStr);
// 业务处理
} catch (Exception e) {
logger.error("RepaymentSuccessMessageListener.onMessage() Exception: ", e);
}
logger.info("RepaymentSuccessMessageListener.onMessage() end...");
}
}
二、rabbitmq的xml配置
1、消费者配置:
(1)连接rabbitmq服务器,因此需要ip地址,端口,用户名和密码;
(2)声明队列名称;
(3)声明交换机以及交换机类型,将队列与交换机通过路由键绑定起来;
(4)声明消费者,消费者监听队列,将监听方法绑定到队列中,一旦队列中有消息,消费者就进行消费。
2、生产者配置:
生产者与消费者前3步配置都是一样的操作,不同的是需要配置生产者类,将交换机、路由键、以及rabbitTemplate注入到生产者类中。
通常可以将生产者和消费者配置在一个xml文件中,这样方便管理。rabbitmq配置如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<!-- 公共部分开始 -->
<!-- 创建连接信息 连接安装好的rabbitmq服务 -->
<rabbit:connection-factory id="connectionFactory" host="${sales.rmq.host}" port="${sales.rmq.port}"
username="${sales.rmq.username}" password="${sales.rmq.password}"/>
<rabbit:admin connection-factory="connectionFactory"/>
<!-- 声明队列(可以声明多个队列) 没有特殊情况,其他参数都用默认的即可 -->
<rabbit:queue name="${cls.sales.rmq.queueName}" id="queue_1"/>
<!-- 声明交换机,通过路由键绑定到指定的队列 -->
<rabbit:direct-exchange id="exchange_1" name="${cls.sales.rmq.exchangeName}">
<rabbit:bindings>
<rabbit:binding queue="queue_1" key="${cls.sales.rmq.routingKey}"/>
</rabbit:bindings>
</rabbit:direct-exchange>
<!-- 公共部分结束 -->
<!-- 生产者部分开始 可配置多个生产者 -->
<!-- Creates a rabbit template (org.springframework.amqp.rabbit.core.RabbitTemplate) for convenient access to the broker -->
<rabbit:template exchange="${cls.sales.rmq.exchangeName}" id="rabbitTemplate"
connection-factory="connectionFactory"/>
<!-- 发送消息的类,即生产者 -->
<bean id="msgProducer" class="com.xdg.sales.mq.Cls2SalesMqSender">
<!-- value中的值就是交换机,路由键,他们的值必须与上面配置的一样 -->
<property name="exchangeName" value="${cls.sales.rmq.exchangeName}"/>
<property name="routingKey" value="${cls.sales.rmq.routingKey}"/>
<property name="rabbitTemplate" ref="rabbitTemplate"/>
</bean>
<!-- 生产者部分结束 -->
<!-- 消费者部分开始 可配置多个消费者 -->
<!-- 消费者类,需要实现MessageListener消息监听器接口,用于监听消息 -->
<bean id="repaymentSuccessMessageListener" class="com.xdg.sales.mq.RepaymentSuccessMessageListener"/>
<bean id="loanSuccessMessageListener" class="com.xdg.sales.mq.LoanSuccessMessageListener"/>
<!-- concurrency是消费者个数,prefetch是每个消费者缓存到客户端队列的个数 -->
<rabbit:listener-container connection-factory="connectionFactory" concurrency="2" prefetch="50">
<!-- 监听方法可以配置多个 -->
<rabbit:listener queue-names="${cls.sales.rmq.queueName}" ref="repaymentSuccessMessageListener"
method="onMessage"/>
<rabbit:listener queue-names="${cls.sales.rmq.queueName}" ref="loanSuccessMessageListener"
method="onMessage"/>
</rabbit:listener-container>
<!-- 消费者部分结束 -->
</beans>
里面的配置信息通常配置在外部,这样方便修改,只需要在xml配置文件中引入即可。
三、总结
只要消息被消费了其他的消费者就没法消费了。例如:有两条消息,如果只有一个消费者,那他将会顺序消费者两条消息,如果有两个消费者,则一人消费一个消息。如果只有一条消息,但有两个消费者,则这条消息只能被其中一个消费者消费,谁来消费这条消息,取决于配置文件消费者的配置顺序。