Rabbitmq基础知识

Rabbitmq基础知识

文章目录

  • Rabbitmq基础知识
    • mq的基本概念
    • mq的优势和劣势
    • mq的劣势
    • 常见的mq的产品
    • RabbitMq简介
    • 安装
    • 简单队列的代码演示
      • provider
      • consumer
    • 常见的几种消息策略
    • 交换机类型
    • 工作模式
    • 订阅模式
    • Routing(路由)
    • Topics工作模式(通配符)
    • spring整合rabbitmq(生产者)
    • spring整合rabbitmq(消费者)
    • spring boot整合rabbitmq生产者
    • spring boot整合rabbitmq消费者
    • rabbitmq高级特性
      • 消息的可靠投递
        • 确认模式
        • 回退模式
      • consumer ack
      • 消费端限流
      • TTL
      • 单独设置消息的过期时间
      • 死信队列
    • rabbitmq的应用
    • rabbitmq的集群搭建

黑马
看到第26集

mq的基本概念

Rabbitmq基础知识_第1张图片

mq的优势和劣势

Rabbitmq基础知识_第2张图片

应用解耦
Rabbitmq基础知识_第3张图片

Rabbitmq基础知识_第4张图片

异步提速
Rabbitmq基础知识_第5张图片
Rabbitmq基础知识_第6张图片
消峰填谷

Rabbitmq基础知识_第7张图片
消峰填谷
Rabbitmq基础知识_第8张图片

mq的劣势

Rabbitmq基础知识_第9张图片
Rabbitmq基础知识_第10张图片

常见的mq的产品

Rabbitmq基础知识_第11张图片

RabbitMq简介

Rabbitmq基础知识_第12张图片
Rabbitmq基础知识_第13张图片
Rabbitmq基础知识_第14张图片
Rabbitmq基础知识_第15张图片
Rabbitmq基础知识_第16张图片
JMS
Rabbitmq基础知识_第17张图片

安装

进入到rabbitmq的sbin目录,双击rabbitmq-server.bat,如果出现如下页面则代表启动成功

Rabbitmq基础知识_第18张图片
进入管理控制台
在浏览器地址栏中输入:http://localhost:15672,看到如下页面则代表启动成功
初始化:用户名和密码均为guest

Rabbitmq基础知识_第19张图片

简单队列的代码演示

provider

结合下面这张图写代码
Rabbitmq基础知识_第20张图片

//		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();

consumer

	//		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);
//		注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
	}

常见的几种消息策略

Rabbitmq基础知识_第21张图片
Rabbitmq基础知识_第22张图片

交换机类型

type:交换机类型
		 *        DIRECT("direct"):定向
		 *        FANOUT("fanout")  扇形(也就是广播,发送到每个队列)
		 *        TOPIC("topic"),   通配符的方式
		 *        HEADERS("headers");  通过参数匹配 (很少用)

工作模式

Rabbitmq基础知识_第23张图片
Rabbitmq基础知识_第24张图片

这里为了测试,需要创建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);
//		注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
	}

在这里插入图片描述

订阅模式

Rabbitmq基础知识_第25张图片

生产者

@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);
//		注意:消费者不要关闭资源,如果资源被关闭了,它就无法对队列中的消息进行监听了
		}

Routing(路由)

发送的消息的routingkey如果和指定队列的routingkey相同,则交换机就把消息转发给对应的队列。

Rabbitmq基础知识_第26张图片
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="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的代码一样(只是将要接收的队列名字不一样就行了)

Topics工作模式(通配符)

通过通配符将消息转发到指定队列

注意:这里的通配符: *:匹配1个单词 #:0个或多个单词
Rabbitmq基础知识_第27张图片

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和上面这个一样,只是获取消息的队列的名字不一样而已

spring整合rabbitmq(生产者)

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");
	}
}

spring整合rabbitmq(消费者)

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();
		}
	}

}

spring boot整合rabbitmq生产者

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);
	}
}

spring boot整合rabbitmq消费者

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.测试

启动项目测试,看是否打印日志

rabbitmq高级特性

Rabbitmq基础知识_第28张图片

消息的可靠投递

Rabbitmq基础知识_第29张图片

确认模式

这里采用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中将确认开启

Rabbitmq基础知识_第30张图片

回退模式

Rabbitmq基础知识_第31张图片

将消息发送给交换机后,交换机发给队列失败,此时消息会丢弃或回退给发送方。

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中一定要开启回退模式

consumer ack

Rabbitmq基础知识_第32张图片

注意:系统默认采用自动签收的方式,下面这里是手动签收。

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方法

消费端限流

注意:限流与消费端有关

Rabbitmq基础知识_第33张图片
需满足以下两个条件
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);
	}

}



监听器

Rabbitmq基础知识_第34张图片

TTL

Rabbitmq基础知识_第35张图片
Rabbitmq基础知识_第36张图片
图形化界面操作步骤
1.使用图形化控制台添加一个队列并设置队列存活时间
Rabbitmq基础知识_第37张图片

2.创建一个交换机
Rabbitmq基础知识_第38张图片
3.交换机绑定队列
Rabbitmq基础知识_第39张图片
4.发布消息
Rabbitmq基础知识_第40张图片

代码操作步骤
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);
	}

死信队列

如果你的消息和死信作了一个绑定,那么当你的消息被销毁了后,该消息会被发送给死信交换机,从而死xingh
Rabbitmq基础知识_第41张图片

rabbitmq的应用

Rabbitmq基础知识_第42张图片

rabbitmq的集群搭建

Rabbitmq基础知识_第43张图片

你可能感兴趣的:(rabbitmq,分布式,java)