RabbitMQ是用erlang實現的消息隊列系統,遵循AMQP(高級消息隊列協議)協議。性能還有可擴展性優於其他相似的框架,當然,新星kafka也不錯,大家可以上網查一下各種MQ框架的優缺點。
參考一下其他文章:http://blog.csdn.net/linsongbin1/article/details/47781187
RabbitMQ主要有三種交換器:direct、fanout、topic
direct就是一對一傳輸
fanout就是匹配傳輸
topic就是主題分發傳輸
還是看代碼吧
maven構建:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xin</groupId>
<artifactId>com.xin.rabbitmq</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<!-- spring版本號 -->
<spring.version>3.2.8.RELEASE</spring.version>
<!-- log4j日誌文件管理包版本 -->
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<!-- junit版本號 -->
<junit.version>4.10</junit.version>
</properties>
<dependencies>
<!-- 添加Spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--單元測試依賴 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 日誌文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!--spring單元測試依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!--rabbitmq依賴 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.1.Final</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${basedir}/target/classes</targetPath>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<targetPath>${basedir}/target/resources</targetPath>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warSourceExcludes>${warExcludes}</warSourceExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
log4j的配置文件:log4j.properties
log4j.rootLogger=DEBUG,Console,Stdout
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.appender.Stdout = org.apache.log4j.DailyRollingFileAppender
log4j.appender.Stdout.File = E://logs/log.log
log4j.appender.Stdout.Append = true
log4j.appender.Stdout.Threshold = DEBUG
log4j.appender.Stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
spring的配置文件:application.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<import resource="classpath*:rabbitMq.xml" />
<!-- 掃描指定package下所有帶有如@controller,@services,@resource,@ods並把所註釋的註冊爲Spring Beans -->
<context:component-scan base-package="com.xin.consumer,com.xin.producer" />
<!-- 激活annotation功能 -->
<context:annotation-config />
<!-- 激活annotation功能 -->
<context:spring-configured />
</beans>
rabbitMq的配置文件:rabbitMq.xml
<?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/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">
<!--配置connection-factory,指定連接rabbit server參數 -->
<rabbit:connection-factory id="connectionFactory"
username="guest" password="guest" host="localhost" port="5672" />
<!--direct 一對一傳輸-->
<!--定義rabbit template用於數據的接收和發送 -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
exchange="exchangeTest" />
<!--通過指定下面的admin信息,當前producer中的exchange和queue會在rabbitmq服務器上自動生成 -->
<rabbit:admin connection-factory="connectionFactory" />
<!--定義queue -->
<rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />
<!-- 定義direct exchange,綁定queueTest -->
<rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">
<rabbit:bindings>
<rabbit:binding queue="queueTest" key="queueTestKey"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
<!-- 消息接收者 -->
<bean id="messageReceiver" class="com.xin.consumer.MessageConsumer"></bean>
<!-- queue litener 觀察 監聽模式 當有消息到達時會通知監聽在對應的隊列上的監聽對象-->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="queueTest" ref="messageReceiver"/>
</rabbit:listener-container>
<!--topic 匹配傳輸-->
<rabbit:template id="topicTemplate" connection-factory="connectionFactory"
exchange="topicExchange"/>
<!--定義queue -->
<rabbit:queue name="topicQueue" durable="true" auto-delete="false" exclusive="false" />
<!--topic交換器 pattern與topicTemplate.convertAndSend("foo.bar",message);第一個參數匹配-->
<rabbit:topic-exchange name="topicExchange">
<rabbit:bindings>
<rabbit:binding queue="topicQueue" pattern="info.*" />
</rabbit:bindings>
</rabbit:topic-exchange>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="topic1" queues="topicQueue"/>
</rabbit:listener-container>
<bean id="topic1" class="com.xin.consumer.TopicConsumer"/>
<!--fanout 把一條消息通過多條隊列傳輸出去-->
<rabbit:template id="fanoutTemplate" connection-factory="connectionFactory"
exchange="fanoutExchange"/>
<!--定義queue -->
<rabbit:queue name="fanoutQueue" durable="true" auto-delete="false" exclusive="false" />
<rabbit:queue name="fanoutQueue2" durable="true" auto-delete="false" exclusive="false" />
<!--topic交換器-->
<rabbit:fanout-exchange name="fanoutExchange">
<rabbit:bindings>
<rabbit:binding queue="fanoutQueue"></rabbit:binding>
<rabbit:binding queue="fanoutQueue2"></rabbit:binding>
</rabbit:bindings>
</rabbit:fanout-exchange>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="fanoutConsumer" queues="fanoutQueue"/>
<rabbit:listener ref="fanoutConsumer2" method="foo" queues="fanoutQueue2"/>
</rabbit:listener-container>
<bean id="fanoutConsumer" class="com.xin.consumer.FanoutConsumer"/>
<bean id="fanoutConsumer2" class="com.xin.consumer.FanoutConsumer2"/>
</beans>
實現direct交換器的傳輸:
生產端:MessageProducer
package com.xin.producer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* Created by lhx on 2016/9/5 9:56
*
* @Description
*/
@Service
public class MessageProducer {
private Logger logger = LoggerFactory.getLogger(MessageProducer.class);
@Resource
private AmqpTemplate amqpTemplate;
public void sendMessage(Object message){
logger.info("to send message:{}",message);
amqpTemplate.convertAndSend("queueTestKey",message);
}
}
消費端:MessageConsumer
package com.xin.consumer;
import com.xin.producer.MessageProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by lhx on 2016/9/5 9:57
*
* @Description 消費接收
*/
public class MessageConsumer implements MessageListener {
private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
@Override
public void onMessage(Message message) {
logger.info("receive message:{}",message);
System.out.println(new String(message.getBody()));
}
public static void main(final String... args) throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
MessageProducer messageProducer = (MessageProducer) ctx.getBean("messageProducer");
messageProducer.sendMessage("-------------hello,xin3453465465467456456456^^^^^^66666!");
Thread.sleep(1000);
ctx.destroy();
}
}
運行main函數,服務端推消息到客戶端,客戶端就會收到message,打印出來。
2016-09-06 10:29:27,659 [main] INFO [com.xin.producer.TopicProducer] - to send message:++++++++++++++++++hello,xin3453465465467456456456^^^^^^66666!hello,xin
2016-09-06 10:29:27,676 [SimpleAsyncTaskExecutor-1] DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] - Received message: (Body:'++++++++++++++++++hello,xin3453465465467456456456^^^^^^66666!hello,xin'MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, appId=null, clusterId=null, type=null, correlationId=null, replyTo=null, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, deliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=topicExchange, receivedRoutingKey=info.debug, deliveryTag=1, messageCount=0])
(Body:'++++++++++++++++++hello,xin3453465465467456456456^^^^^^66666!hello,xin'MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, appId=null, clusterId=null, type=null, correlationId=null, replyTo=null, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, deliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=topicExchange, receivedRoutingKey=info.debug, deliveryTag=1, messageCount=0])
++++++++++++++++++hello,xin3453465465467456456456^^^^^^66666!hello,xin
其他交換器的實現類似,請參考我的git項目:https://github.com/888xin/rabbitmq