黑马
看到第26集
进入到rabbitmq的sbin目录,双击rabbitmq-server.bat,如果出现如下页面则代表启动成功
进入管理控制台
在浏览器地址栏中输入:http://localhost:15672,看到如下页面则代表启动成功
初始化:用户名和密码均为guest
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
Channel channel=connection.createChannel();
// 5.创建队列
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
, boolean autoDelete, Map arguments)
*/
// 如果没有hjx_quene的队列则会创建该队列,否则不会进行创建
channel.queueDeclare("hjx_queue",true,false,false,null);
// 6.发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
String message="hello world,欢迎跟着黑马大神一起学习rabbitmq";
channel.basicPublish("","hjx_quene",null,message.getBytes());
// 释放资源
channel.close();
connection.close();
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
Channel channel=connection.createChannel();
// 静态内部类
Consumer consumer=new DefaultConsumer(channel){
// 这是一个回调方法 当收到消息后会自动执行该方法
/**
*
* @param consumerTag 消息唯一标识
* @param envelope 获取一些信息 交换机、路由key
* @param properties 配置信息
* @param body 获取到的数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("consumerTag:"+consumerTag);
System.out.println("envelope:"+envelope.getExchange());
System.out.println("properties:"+properties);
System.out.println("body:"+new String(body));
}
};
channel.basicConsume("hjx_queue",true,consumer);
// 注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
}
type:交换机类型
* DIRECT("direct"):定向
* FANOUT("fanout") 扇形(也就是广播,发送到每个队列)
* TOPIC("topic"), 通配符的方式
* HEADERS("headers"); 通过参数匹配 (很少用)
这里为了测试,需要创建2个consumer,然后启动consumer和provider。当consumer监听到有消息时就会将对应的消息打印出来。代码如下:
provider
public void sendMs() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
Channel channel=connection.createChannel();
// 5.创建队列
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
, boolean autoDelete, Map arguments)
*/
// 如果没有hjx_quene的队列则会创建该队列,否则不会进行创建
channel.queueDeclare("hjx_queue",true,false,false,null);
// 6.发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
// 这里为了测试方便,发送10条消息,因为时工作模式下的消息队列嘛
for(int i=0;i<10;i++){
String message="hello world,欢迎跟着黑马大神一起学习rabbitmq"+(i+1);
channel.basicPublish("","hjx_quene",null,message.getBytes());
}
// 释放资源
channel.close();
connection.close();
}
consumer
注意:这里的consumer,创建2个内容一模一样的就可以了。只要文件名不一样就行。
public void Test1() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
Channel channel=connection.createChannel();
// 静态内部类
Consumer consumer=new DefaultConsumer(channel){
// 这是一个回调方法 当收到消息后会自动执行该方法
/**
*
* @param consumerTag 消息唯一标识
* @param envelope 获取一些信息 交换机、路由key
* @param properties 配置信息
* @param body 获取到的数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
/*System.out.println("consumerTag:"+consumerTag);
System.out.println("envelope:"+envelope.getExchange());
System.out.println("properties:"+properties);*/
System.out.println("body:"+new String(body));
}
};
channel.basicConsume("hjx_queue",true,consumer);
// 注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
}
生产者
@Test
public void test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
/**
* exchange:交换机名称
* type:交换机类型
* DIRECT("direct"):定向
* FANOUT("fanout") 扇形(也就是广播,发送到每个队列)
* TOPIC("topic"), 通配符的方式
* HEADERS("headers"); 通过参数匹配
* durable:是否持久化
* autoDelete:是否自动删除
* internal:内部使用。一般为false
* arguments:参数
*
* exchangeDeclare(String exchange, BuiltinExchangeType type,
* boolean durable, boolean autoDelete, Map arguments)
*
*
*/
Channel channel=connection.createChannel();
String exchangeName="fanout_exchange";
channel.exchangeDeclare(exchangeName,BuiltinExchangeType.FANOUT,true,false,false,null);
String quueName1="quue_1";
String quueName2="quue_2";
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
boolean autoDelete, Map arguments)
*/
// 声明队列,这里需要声明多个队列
channel.queueDeclare(quueName1,true,false,false,null);
channel.queueDeclare(quueName2,true,false,false,null);
// 绑定队列和交换机的关系
/**
* queue:队列的名称
* exchange:交换机的名称
* routingKey:路由key 如果交换机的类型为fanout,则routingKey=""
*
* queueBind(String queue, String exchange, String routingKey)
*/
channel.queueBind(quueName1,exchangeName,"");
channel.queueBind(quueName2,exchangeName,"");
// 发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
String message="日志信息";
//这样交换机就会将消息转发给对应的2个队列
channel.basicPublish(exchangeName,"",null,message.getBytes());
// 释放资源
channel.close();
connection.close();
}
消费者
consumer1
@Test
public void test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
/**
* exchange:交换机名称
* type:交换机类型
* DIRECT("direct"):定向
* FANOUT("fanout") 扇形(也就是广播,发送到每个队列)
* TOPIC("topic"), 通配符的方式
* HEADERS("headers"); 通过参数匹配
* durable:是否持久化
* autoDelete:是否自动删除
* internal:内部使用。一般为false
* arguments:参数
*
* exchangeDeclare(String exchange, BuiltinExchangeType type,
* boolean durable, boolean autoDelete, Map arguments)
*
*
*/
Channel channel=connection.createChannel();
String exchangeName="fanout_exchange";
channel.exchangeDeclare(exchangeName,BuiltinExchangeType.FANOUT,true,false,false,null);
String quueName1="quue_1";
String quueName2="quue_2";
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
boolean autoDelete, Map arguments)
*/
// 声明队列,这里需要声明多个队列
channel.queueDeclare(quueName1,true,false,false,null);
channel.queueDeclare(quueName2,true,false,false,null);
// 绑定队列和交换机的关系
/**
* queue:队列的名称
* exchange:交换机的名称
* routingKey:路由key 如果交换机的类型为fanout,则routingKey=""
*
* queueBind(String queue, String exchange, String routingKey)
*/
channel.queueBind(quueName1,exchangeName,"");
channel.queueBind(quueName2,exchangeName,"");
// 发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
String message="日志信息";
//这样交换机就会将消息转发给对应的2个队列
channel.basicPublish(exchangeName,"",null,message.getBytes());
// 释放资源
channel.close();
connection.close();
}
consumer2
@Test
public void Test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
Channel channel=connection.createChannel();
// 队列的名字
String quueName1="quue_1";
String quueName2="quue_2";
// 静态内部类
Consumer consumer=new DefaultConsumer(channel){
// 这是一个回调方法 当收到消息后会自动执行该方法
/**
*
* @param consumerTag 消息唯一标识
* @param envelope 获取一些信息 交换机、路由key
* @param properties 配置信息
* @param body 获取到的数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
System.out.println("将日志信息保存到数据库.....");
}
};
channel.basicConsume(quueName2,true,consumer);
// 注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
}
发送的消息的routingkey如果和指定队列的routingkey相同,则交换机就把消息转发给对应的队列。
public void test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
/**
* exchange:交换机名称
* type:交换机类型
* DIRECT("direct"):定向
* FANOUT("fanout") 扇形(也就是广播,发送到每个队列)
* TOPIC("topic"), 通配符的方式
* HEADERS("headers"); 通过参数匹配
* durable:是否持久化
* autoDelete:是否自动删除
* internal:内部使用。一般为false
* arguments:参数
*
* exchangeDeclare(String exchange, BuiltinExchangeType type,
* boolean durable, boolean autoDelete, Map arguments)
*
*
*/
Channel channel=connection.createChannel();
String exchangeName="direct_exchange";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT,true,false,false,null);
String quueName1="quue_1";
String quueName2="quue_2";
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
boolean autoDelete, Map arguments)
*/
// 声明队列,这里需要声明多个队列
channel.queueDeclare(quueName1,true,false,false,null);
channel.queueDeclare(quueName2,true,false,false,null);
// 绑定队列和交换机的关系
/**
* queue:队列的名称
* exchange:交换机的名称
* routingKey:路由key 如果交换机的类型为fanout,则routingKey=""
*
* queueBind(String queue, String exchange, String routingKey)
*/
// 队列1的绑定
channel.queueBind(quueName1,exchangeName,"error");
// 队列2的绑定
channel.queueBind(quueName2,exchangeName,"info");
channel.queueBind(quueName2,exchangeName,"warning");
channel.queueBind(quueName2,exchangeName,"error");
// 发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
String message="日志信息";
//这样交换机就会将消息转发给对应的2个队列 注意:这里的第2个参数info为消息的路由key,它会和队列的路由key进行匹配
channel.basicPublish(exchangeName,"info",null,message.getBytes());
// 释放资源
channel.close();
connection.close();
}
consumer1
public void Test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
Channel channel=connection.createChannel();
// 队列的名字
String quueName1="quue_1";
String quueName2="quue_2";
// 静态内部类
Consumer consumer=new DefaultConsumer(channel){
// 这是一个回调方法 当收到消息后会自动执行该方法
/**
*
* @param consumerTag 消息唯一标识
* @param envelope 获取一些信息 交换机、路由key
* @param properties 配置信息
* @param body 获取到的数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
System.out.println("将日志消息打印到控制台.....");
}
};
channel.basicConsume(quueName1,true,consumer);
// 注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
}
注意:另外一个consumer2和上面这里的consumer1的代码一样(只是将要接收的队列名字不一样就行了)
通过通配符将消息转发到指定队列
provider
public void test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
/**
* exchange:交换机名称
* type:交换机类型
* DIRECT("direct"):定向
* FANOUT("fanout") 扇形(也就是广播,发送到每个队列)
* TOPIC("topic"), 通配符的方式
* HEADERS("headers"); 通过参数匹配
* durable:是否持久化
* autoDelete:是否自动删除
* internal:内部使用。一般为false
* arguments:参数
*
* exchangeDeclare(String exchange, BuiltinExchangeType type,
* boolean durable, boolean autoDelete, Map arguments)
*
*
*/
Channel channel=connection.createChannel();
String exchangeName="topic_exchange";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC,true,false,false,null);
String quueName1="quue_1";
String quueName2="quue_2";
/*
durable:持久的
exclusive:1.该队列是否只能有一个消费者对其进行监听 2.当连接关闭时是否删除队列
autoDelete:是否自动删除(当没有消费者时,是否自动删除)
queueDeclare(String queue, boolean durable, boolean exclusive
boolean autoDelete, Map arguments)
*/
// 声明队列,这里需要声明多个队列
channel.queueDeclare(quueName1,true,false,false,null);
channel.queueDeclare(quueName2,true,false,false,null);
// 绑定队列和交换机的关系
/**
* queue:队列的名称
* exchange:交换机的名称
* routingKey:路由key 如果交换机的类型为fanout,则routingKey=""
*
* queueBind(String queue, String exchange, String routingKey)
*/
// 队列1的绑定
/**
* routingkey:系统名称.日志级别
* 需求:将error级别的日志存入数据库,所有order系统的日志也存入数据库
*
*/
channel.queueBind(quueName1,exchangeName,"#.error");
// 队列2的绑定
channel.queueBind(quueName1,exchangeName,"order.*");
channel.queueBind(quueName2,exchangeName,"*.*");
// 发送消息
/*
1.exchange:交换机名称 (简单模式下使用默认的交换机,即设置为空字符串即可。
2.routingKey:路由键,只要routingKey和队列名称一样,该消息就会发送到该队列中
3.props:配置信息
4.发送的内容
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
*/
String message="日志信息";
//这样交换机就会将消息转发给对应的2个队列 注意:这里的第2个参数info为消息的路由key,它会和队列的路由key进行匹配
channel.basicPublish(exchangeName,"order.info",null,message.getBytes());
// 释放资源
channel.close();
connection.close();
}
consumer
public void Test() throws IOException, TimeoutException {
// 1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
// 2.设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("hjx");
factory.setPassword("123456");
// 3.创建连接
Connection connection =factory.newConnection();
// 4.创建channel
/*
1.quene:队列名称
2.autoAck:是否确认(消费者收到消息了后自动给队列回复收到了)
3.callback:回调函数
basicConsume(String queue, boolean autoAck, Consumer callback)
*/
Channel channel=connection.createChannel();
// 队列的名字
String quueName1="quue_1";
String quueName2="quue_2";
// 静态内部类
Consumer consumer=new DefaultConsumer(channel){
// 这是一个回调方法 当收到消息后会自动执行该方法
/**
*
* @param consumerTag 消息唯一标识
* @param envelope 获取一些信息 交换机、路由key
* @param properties 配置信息
* @param body 获取到的数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
System.out.println("将日志消息打印到控制台.....");
}
};
channel.basicConsume(quueName1,true,consumer);
// 注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
}
注意:另外一个consume和上面这个一样,只是获取消息的队列的名字不一样而已
1.导入依赖
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
<version>2.1.8.RELEASEversion>
dependency>
2.application配置文件
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=root
spring.rabbitmq.password=123
spring.rabbitmq.virtual-host=/
3.配置xml
<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/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<rabbit:connection-factory id="connectionFactory"
host="${spring.rabbitmq.host}" port="${spring.rabbitmq.port}" username="${spring.rabbitmq.username}" password="${spring.rabbitmq.password}" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="que_cat" auto-declare="true" durable="true" />
<rabbit:queue name="que_pig" auto-declare="true" durable="true" />
<rabbit:direct-exchange name="IExchange"
id="IExchange">
<rabbit:bindings>
<rabbit:binding queue="que_cat" key="que_cat_key" />
<rabbit:binding queue="que_pig" key="que_pig_key" />
rabbit:bindings>
rabbit:direct-exchange>
<bean id="jsonMessageConverter"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
<rabbit:template id="rabbitTemplate"
connection-factory="connectionFactory" exchange="IExchange"
message-converter="jsonMessageConverter" />
beans>
4.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-rabbitmq-send.xml")
public class Test {
// 注入 rabbitTemplate
@Autowired
private RabbitTemplate rabbitTemplate;
@org.junit.Test
public void rabbitTest(){
// 发送消息 路由模式下的发送
rabbitTemplate.convertAndSend("que_cat_key","hello world");
}
}
1.依赖
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
<version>2.1.8.RELEASEversion>
dependency>
2.xml配置
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<rabbit:connection-factory id="connectionFactory"
host="${spring.rabbitmq.host}" port="${spring.rabbitmq.port}" username="${spring.rabbitmq.username}" password="${spring.rabbitmq.password}" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="que_cat" auto-declare="true" durable="true" />
<rabbit:queue name="que_pig" auto-declare="true" durable="true" />
<bean name="catHandler" class="com.hjx.monitor.CatHandler" />
<bean name="pigHandler" class="com.hjx.monitor.PigHandler" />
<rabbit:listener-container
connection-factory="connectionFactory">
<rabbit:listener ref="catHandler" queues="que_cat" />
<rabbit:listener ref="pigHandler" queues="que_pig" />
rabbit:listener-container>
beans>
3.properties配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=root
spring.rabbitmq.password=123
spring.rabbitmq.virtual-host=/
4.编写监听器实现MessageListener接口实现onMessage方法
package com.hjx.monitor;
import java.io.IOException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CatHandler implements MessageListener {
private static final ObjectMapper MAPPER = new ObjectMapper();
public void onMessage(Message msg) {
try {
//msg就是rabbitmq传来的消息
// 使用jackson解析
// msg.getBody():消息内容
JsonNode jsonData = MAPPER.readTree(msg.getBody());
System.out.println("我是可爱的小猫,我的id是" + jsonData.get("id").asText()
+ ",我的名字是" + jsonData.get("name").asText());
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
dependencies>
2.编写配置文件
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: root
password: 123
virtual-host: /
3.编写配置类
package com.hjx.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
//交换机的名称
public static final String exchangeName="boot_topic";
//队列的名称
public static final String queueName="boot_quue";
/**
* 1.交换机
* 2.队列
* 3.交换机和队列的绑定关系
*/
// 1.交换机
@Bean("exchange")
public Exchange bootExchange(){
return ExchangeBuilder.topicExchange(exchangeName).durable(true).build();
}
// 2.队列
@Bean("Queue")
public Queue bootQueue(){
return QueueBuilder.durable(queueName).build();
}
//3.交换机和队列的绑定关系
@Bean
public Binding bootBind(@Qualifier("exchange") Exchange exchange,@Qualifier("Queue") Queue queue ){
return BindingBuilder.bind(queue).to(exchange).with("boot.#").noargs();
}
}
4.测试
/**
* @Nullable:表示可以传入空值
*/
@SpringBootTest
public class ProviderTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSend(){
String ms="hello,spring boot-rabbitmq!";
rabbitTemplate.convertSendAndReceive(RabbitConfig.exchangeName,"boot.hello",ms);
}
}
1.导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
dependencies>
2.配置文件
spring:
rabbitmq:
virtual-host: /
host: 127.0.0.1
port: 5672
username: root
password: 123
3.编写配置类
/监听队列
@Component
public class RabbitListenQue {
// 监听 名为 boot_quue的队列
@RabbitListener(queues="boot_quue")
public void ListnerQue(Message message){
System.out.println("message:"+message);
}
}
4.测试
启动项目测试,看是否打印日志
这里采用spring的方式,这里的代码和spring整合rabbitmq差不多,只需要改变一小部分就可以了!
xml文件
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<rabbit:connection-factory id="connectionFactory"
host="${spring.rabbitmq.host}"
port="${spring.rabbitmq.port}"
username="${spring.rabbitmq.username}"
password="${spring.rabbitmq.password}"
publisher-confirms="true"
/>
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="que_cat" auto-declare="true" durable="true" />
<rabbit:queue name="que_pig" auto-declare="true" durable="true" />
<rabbit:direct-exchange name="IExchange"
id="IExchange">
<rabbit:bindings>
<rabbit:binding queue="que_cat" key="que_cat_key" />
<rabbit:binding queue="que_pig" key="que_pig_key" />
rabbit:bindings>
rabbit:direct-exchange>
<bean id="jsonMessageConverter"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
<rabbit:template id="rabbitTemplate"
connection-factory="connectionFactory" exchange="IExchange"
message-converter="jsonMessageConverter" />
<rabbit:queue id="test_quue_confirm" name="test_quue_confirm" >rabbit:queue>
<rabbit:direct-exchange name="test_exchange_confirm">
<rabbit:bindings>
<rabbit:binding queue="test_quue_confirm" key="confirm">rabbit:binding>
rabbit:bindings>
rabbit:direct-exchange>
beans>
测试
package com.hjx;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-rabbitmq-send.xml")
public class Test {
// 注入 rabbitTemplate
@Autowired
private RabbitTemplate rabbitTemplate;
@org.junit.Test
public void rabbitTest(){
// 发送消息 路由模式下的发送
rabbitTemplate.convertAndSend("que_cat_key","hello world");
}
@org.junit.Test
public void confirmTest(){
// 定义回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){
/**
*
* @param correlationData 参数的信息
* @param ack 交换机是否成功收到信息 true:代表成功 false:代表失败
* @param cause 失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause){
if(ack){
System.out.println("接收消息成功");
System.out.println("confirm方法被执行");
}else{
System.out.println("接收消息fail");
}
}
});
// 发送消息
rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","确认消息的日志");
}
}
注意点:
一定要在xml中将确认开启
将消息发送给交换机后,交换机发给队列失败,此时消息会丢弃或回退给发送方。
1.xml配置
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<rabbit:connection-factory id="connectionFactory"
host="${spring.rabbitmq.host}"
port="${spring.rabbitmq.port}"
username="${spring.rabbitmq.username}"
password="${spring.rabbitmq.password}"
publisher-confirms="true"
publisher-returns="true"
/>
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="que_cat" auto-declare="true" durable="true" />
<rabbit:queue name="que_pig" auto-declare="true" durable="true" />
<rabbit:direct-exchange name="IExchange"
id="IExchange">
<rabbit:bindings>
<rabbit:binding queue="que_cat" key="que_cat_key" />
<rabbit:binding queue="que_pig" key="que_pig_key" />
rabbit:bindings>
rabbit:direct-exchange>
<bean id="jsonMessageConverter"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
<rabbit:template id="rabbitTemplate"
connection-factory="connectionFactory" exchange="IExchange"
message-converter="jsonMessageConverter" />
<rabbit:queue id="test_quue_confirm" name="test_quue_confirm" >rabbit:queue>
<rabbit:direct-exchange name="test_exchange_confirm">
<rabbit:bindings>
<rabbit:binding queue="test_quue_confirm" key="confirm">rabbit:binding>
rabbit:bindings>
rabbit:direct-exchange>
beans>
2.测试
// 回退模式的测试
@org.junit.Test
public void BackTest(){
// 设置交换机处理失败消息的模式
rabbitTemplate.setMandatory(true); // 这样交换机就会将发送失败的消息返回给发送方
rabbitTemplate.setReturnCallback(
new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replycode, String replyText, String exchange, String routingKey) {
System.out.println("回退的消息为:"+message);
System.out.println("replycode:"+replycode);
System.out.println("replyText:"+replyText);
System.out.println("exchange:"+exchange);
System.out.println("routingKey:"+routingKey);
System.out.println("消息回退执行了");
}
}
);
}
注意点
xml中一定要开启回退模式
注意:系统默认采用自动签收的方式,下面这里是手动签收。
xml文件
关键部分
<rabbit:listener-container
connection-factory="connectionFactory" acknowledge="manual" >
<rabbit:listener ref="catHandler" queues="que_cat" />
<rabbit:listener ref="pigHandler" queues="que_pig" />
rabbit:listener-container>
监听器
package com.hjx.monitor;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
/**
* 默认为自动签收
* 1.这里需要设置为手动签收 acknowledge="manual"
* 2.让监听器实现ChannelAwareMessageListener接口(是MessageListener的子接口)
* 3.如果消息处理成功,则调用channel的basicAck()签收,否者调用channel的basicNack()拒绝签收,让broker重新发送消息
*
*
*
*/
public class CatHandler implements ChannelAwareMessageListener {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public void onMessage(Message message, Channel channel) throws Exception {
//获取消息的tag(标签)
long deliveryTag=message.getMessageProperties().getDeliveryTag();
System.out.println(new String(message.getBody()));
// 处理业务逻辑
System.out.println("处理业务逻辑");
try {
channel.basicAck(deliveryTag,true);
}catch (Exception e){
//拒绝签收 第3个参数:true代表消息重新发送
channel.basicNack(deliveryTag,true,true);
}
}
}
注意点:
1.xml文件中的rabbit:listener-container一定要设置acknowledge=“manual”:代表手动签收。
2.监听器需要实现ChannelAwareMessageListener接口(MessageListener接口的子接口)onMessage方法
注意:限流与消费端有关
需满足以下两个条件
1.手动确认 ( 只有当手动确认后才能拉去队列中的下一条消息)
2.配置属性(xml中进行配置)rabbit:listener-container节点中进行配置 perfetch属性
prefetch=n:表示消费端每次从队列中拉取n条消息
操作步骤
/**
*
* 限流
* 需要满足以下几个条件:
* 1.手动确认 ( 只有当手动确认后才能拉去队列中的下一条消息)
* 2.配置属性(xml中进行配置)rabbit:listener-container节点中进行配置 perfetch属性
* prefetch=n:表示消费端每次从队列中拉取n条消息
*
*/
public class CurrentLimit implements ChannelAwareMessageListener {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public void onMessage(Message message, Channel channel) throws Exception {
// 获取消息
System.out.println(new String(message.getBody()));
// 处理业务逻辑
// 手动签收
channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
}
}
监听器
图形化界面操作步骤
1.使用图形化控制台添加一个队列并设置队列存活时间
代码操作步骤
1.声明一个队列并设置队列的过期时间
<rabbit:queue name="test_quue_ttl" auto-declare="true" durable="true">
<rabbit:queue-arguments>
<entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"/>
rabbit:queue-arguments>
rabbit:queue>
2.声明交换机并绑定队列
<rabbit:topic-exchange name="test_exchange_ttl">
<rabbit:bindings>
<rabbit:binding pattern="ttl.#" queue="test_quue_ttl">rabbit:binding>
rabbit:bindings>
rabbit:topic-exchange>
3.测试
// TTL测试
@org.junit.Test
public void TTL_test(){
rabbitTemplate.convertAndSend("test_exchange_ttl","ttl.hh","TTL的测试-helloworld!!");
}
注意:如果队列的时间和消息的时间都设置话,则默认以时间短的为准!!
消息过期后,只有消息在队列顶端,才会判断其是否过期(如果过期,则将该消息移除掉),而不是说消息的过期时间到了,该消息就会被移除。所以一般都设置队列的过期时间
// 单独设置消息的过期时间
@org.junit.Test
public void setMessageDiedtime(){
// 消息后处理器 可以设置一些参数
MessagePostProcessor postProcessor=new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置5秒后过期
message.getMessageProperties().setExpiration("5000");
return message;
}
};
rabbitTemplate.convertAndSend("test_exchange_ttl","ttl.hh","TTL的测试-helloworld!!", postProcessor);
}