rabbitmq,目前比较火的一个MQ消息队列。他有以下特点:
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。
AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。
RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:
-
可靠性(Reliability)
RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。 -
灵活的路由(Flexible Routing)
在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。 -
消息集群(Clustering)
多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。 -
高可用(Highly Available Queues)
队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。 -
多种协议(Multi-protocol)
RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。 -
多语言客户端(Many Clients)
RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。 -
管理界面(Management UI)
RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。 -
跟踪机制(Tracing)
如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。 -
插件机制(Plugin System)
RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件
下面教大家一下与spring的整合使用
整合
1.加入pom依赖
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
2.编写rabitmq.properties配置文件
mq.host=106.15.202.0
mq.username=root
mq.password=root
mq.port=5672
3.编写spring-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-3.0.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd" >
<rabbit:connection-factory id="connectionFactory"
username="${mq.username}" password="${mq.password}" host="${mq.host}" port="${mq.port}"
virtual-host="/" />
<!-- 定义rabbit template 用于数据的接收和发送 -->
<rabbit:template id="amqTemplate" connection-factory="connectionFactory"
exchange="Q_PAY_PPMS_RECON"></rabbit:template>
<!-- 通过指定下面的admin信息,当前productor中的exchange和queue会在rabbitmq服务器上自动生成 -->
<rabbit:admin connection-factory="connectionFactory" />
<!--定义queue 说明:durable:是否持久化 exclusive: 仅创建者可以使用的私有队列,断开后自动删除 auto_delete: 当所有消费客户端连接断开后,是否自动删除队列-->
<rabbit:queue name="chase1" durable="true" auto-delete="false" exclusive="false" />
<rabbit:queue name="chase2" durable="true" auto-delete="false" exclusive="false" />
<rabbit:queue name="chase3" durable="true" auto-delete="false" exclusive="false" />
<!--topic 模式:发送端不是按固定的routing key发送消息,而是按字符串“匹配”发送,接收端同样如此。 -->
<rabbit:topic-exchange name="mq.asdfExChange"
durable="true" auto-delete="false">
<rabbit:bindings>
<!-- 配置多个消费者 根据不同业务类型选择对应消费者 pattern="*.*.test1" -->
<rabbit:binding queue="chase1" pattern="mq.*.send"></rabbit:binding>
<rabbit:binding queue="chase2" pattern="mq.*.send"></rabbit:binding>
<rabbit:binding queue="chase3" pattern="mq.*.send"></rabbit:binding>
</rabbit:bindings>
</rabbit:topic-exchange>
<!-- fanout 模式:客户端中只要是与该路由绑定在一起的队列都会收到相关消息,这类似广播,发送端不管队列是谁,都由客户端自己去绑定,谁需要数据谁去绑定自己的相应队列 -->
<rabbit:fanout-exchange name="delayed_message_exchange" durable="true" auto-delete="false" id="delayed_message_exchange">
<rabbit:bindings>
<rabbit:binding queue="chase1"/>
<rabbit:binding queue="chase2"/>
<rabbit:binding queue="chase3"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
<!--定义direct-exchange direct 消息转换队列 绑定key,意思就是消息与一个特定的路由键匹配,会转发。rabbit:binding:设置消息queue匹配的key -->
<rabbit:direct-exchange name="mq.qwerExChange" durable="true" auto-delete="false">
<rabbit:bindings>
<rabbit:binding queue="chase1" key="mq.qwer.send" ></rabbit:binding>
<rabbit:binding queue="chase2" key="mq.qwer.send2" ></rabbit:binding>
<rabbit:binding queue="chase3" key="mq.qwer.send3" ></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
<!-- 消息接收者 -->
<bean id="asdfConsumer" class="com.rabbitmq.Consumor"></bean>
<bean id="asdfConsumer2" class="com.rabbitmq.Consumor2"></bean>
<bean id="qwerConsumer3" class="com.rabbitmq.Consumor3"></bean>
<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象
acknowledeg = "manual",意为表示该消费者的ack方式为手动-->
<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual">
<rabbit:listener queues="chase1" ref="asdfConsumer"/>
</rabbit:listener-container>
<rabbit:listener-container connection-factory="connectionFactory" >
<rabbit:listener queues="chase2" ref="asdfConsumer2"/>
</rabbit:listener-container>
<rabbit:listener-container connection-factory="connectionFactory" >
<rabbit:listener queues="chase3" ref="qwerConsumer3"/>
</rabbit:listener-container>
</beans>
4.在spring主配置文件中引入刚刚添加的配置文件
5.编写消费者
package com.rabbitmq;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import com.rabbitmq.client.Channel;
/**
* 功能概述 消息接收
* @author chase
*
*/
public class Consumor implements ChannelAwareMessageListener{
/**
* message 消息实体
* Channel 当前通道
*/
public void onMessage(Message message, Channel channel) throws Exception {
// TODO Auto-generated method stub
String msg= new String (message.getBody(),"utf-8");
//消息的标识,false只确认当前一个消息收到,true确认所有consumer获得的消息
/*channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);*/
//ack返回false,并重新回到队列,api里面解释得很清楚
/*channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);*/
//true拒绝消息 false确认接受到消息
channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
System.out.println("消费者1号消费掉了:"+msg+"------->>>>>");
}
}
6.编写Controller类用于发送消息
package com.rabbitmq;
import java.util.HashMap;
import java.util.Map;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
@RestController
@RequestMapping("/send")
public class SendMsgController {
@Autowired
private AmqpTemplate amqpTemplate;
@RequestMapping("/sendMsg")
public String sendAmqbMsg(Model model,@RequestParam(value="msg",defaultValue="hello world!!!")String msg){
if(model!=null&&!"".equals(msg)){
amqpTemplate.convertAndSend("mq.asdfExChange", "mq.asdf.send", msg);
}else{
amqpTemplate.convertAndSend("mq.asdfExChange", "mq.asdf.send", "hello world");
}
return "success";
}
@RequestMapping("/sendMsg2")
public String sendAmqbMsg2(Model model,@RequestParam(value="msg",defaultValue="hello world!!!")String msg){
if(model!=null&&!"".equals(msg)){
amqpTemplate.convertAndSend("delayed_message_exchange","","这个世界很奇妙!!!");
}else{
amqpTemplate.convertAndSend("delayed_message_exchange","", "这个世界很奇妙");
}
return "success";
}
@RequestMapping("/sendMsg3")
public String sendAmqbMsg3(Model model,@RequestParam(value="msg",defaultValue="hello world!!!")String msg){
if(model!=null&&!"".equals(msg)){
amqpTemplate.convertAndSend("mq.qwerExChange", "mq.qwer.send", "神奇的世界!!!");
}else{
amqpTemplate.convertAndSend("mq.qwerExChange", "mq.qwer.send", "神奇的世界");
}
return "success";
}
}
7.添加到tomcat中,运行项目测试
输入地址请求Controller
查看结果
到这里就已经成功啦!!!
附上完整案例下载地址:https://download.csdn.net/download/lzmlzmlzm268/10662803