入门RabbitMQ消息队列结合SSH框架(RabbitMQ非spring封装注解篇)

RabbitMQ我在上一篇讲了怎么配置https://blog.csdn.net/sirenloazhang/article/details/80501900

现在开始正式入门RabbitMQ,首先先不和spring一起使用,单独使用RabbitMQ

下载安装所需的jar包

这里我们需要用到rabbit.client的jar包

如果是用的Maven则

Maven Pom.xml

		
		
		  com.rabbitmq
		  amqp-client
		  4.1.0
		

要其他版本请去http://mvnrepository.com/artifact/com.rabbitmq/amqp-client自己选择


概念


关于消息队列我们需要知道生产者(Producer)和消费者(Consumer),简单的理解就是消息的发送源和接收方

RabbitMQ有几种队列模式,分别为

Simple(简单模式):一个消息只能被一个消费者获取

Work(工作模式):一个消息只能被一个消费者获取,在有多个消费者时,可以用轮询和公平分发

轮询:轮流发给消费者,不管应答数目,傻瓜式分发

公平:根据应答的数目轮流发,比如basicQos( prefetchCount = 1)即应答数目不超过1条,必须关闭自动应答进行手动,而默认是打开自动应答

boolean ack = false ; //打开应答机制

channel.basicConsume(QUEUE_NAME, ack, consumer);

channel.basicAck(delivery.getEnvelope().getDeliveryTag(),ack);

ack为true 时则关闭自动应答

Subscribe(订阅模式):一个消息可以被多个消费者获取(主要由Exchange交换机实现)

Routing(路由模式):一个消息可以被多个消费者获取(主要由Exchange交换机实现),可以定义ExchangeKey

Topic(通配符模式):一个消息可以被多个消费者获取,发送的目的队列(queue)可以由通配符#、*指定


基础的认识了RabbitMQ,现在我们开始测试实例


各个模式的实例,我整合在一个文件里进行测试,以上的几个模式我都写在方法里了(要用去掉注释就行),需要直接调用测试

需要直接Run这几个线程,就可以看到结果,方便入门理解

RabbitMQ连接

package com.test.rabbitmq;

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/** 
* @author Sirenes
* @version 创建时间:2018年5月30日 下午3:04:55 
* 类说明: 
*/
public class ConnectionUtil {
	public static Connection getConnection() throws Exception{
		ConnectionFactory factory = new ConnectionFactory();
		// 设置MabbitMQ所在主机ip或者主机名
		factory.setHost("localhost");
		// 创建一个连接
		Connection connection;
		connection = factory.newConnection();
		return connection;
	}
}

生产者

package com.test.rabbitmq;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author Sirenes
 * @version 创建时间:2018年5月29日 下午11:25:17 类说明:
 */
public class Send {
	private final static String QUEUE_NAME = "hello";

	public static void main(String[] args) throws Exception {
		//new Send().simple();
		//new Send().work();
		//new Send().subscribe();
		//new Send().routing();
		new Send().topic();
	}
	public void simple(){                                    /*Simplemoshi*/
		ConnectionFactory factory = new ConnectionFactory();
		// 设置MabbitMQ所在主机ip或者主机名
		factory.setHost("localhost");
		// 创建一个连接
		Connection connection;
		try {
			connection = factory.newConnection();
			Channel channel = connection.createChannel();
			// 指定一个队列
			channel.queueDeclare(QUEUE_NAME, false, false, false, null);
			// 发送的消息
			String message = "hello world!";
			// 往队列中发出一条消息
			channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
			System.out.println(" [x] Sent '" + message + "'");
			// 关闭频道和连接
			channel.close();
			connection.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 创建一个频道
	}
	public void work() throws Exception{                        /*Work模式*/

		Connection connection = ConnectionUtil.getConnection();
        Channel channel;
		try {
			channel = connection.createChannel();
			channel.queueDeclare(QUEUE_NAME, false, false, false, null);

	        for (int i = 0; i < 50; i++) {
	            String message = "" + i;
	            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());

	            Thread.sleep(i * 10);
	        }

	        channel.close();
	        connection.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        // 声明队列
        
	}
	private final static String EXCHANGE_NAME= "exchange_fanout";
	public void subscribe() throws Exception{                         /*Subscribe模式*/
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();

        // 声明exchange
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        
        // 消息内容
        String message = "Hello world";
        // 与前面不同, 生产者将消息发送给exchange, 而非队列. 若发消息时还没消费者绑定queue与该exchange, 消息将丢失
        channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
        channel.close();
        connection.close();
	}
	
	
	public void routing() throws Exception{                              /*routing模式*/
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();

        // 声明exchange
        channel.exchangeDeclare("exchange_direct", "direct");

        String message = "Hello world";
        // 发送消息, RoutingKey为 insert
        channel.basicPublish("exchange_direct", "insert", null, message.getBytes());

        channel.close();
        connection.close();
	}
	public void topic() throws Exception{
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();

        // 声明exchange
        channel.exchangeDeclare("exchange_topic", "topic");

        String message = "Hello world";
        // 发送消息, 指定RoutingKey
        channel.basicPublish("exchange_topic", "item.delete", null, message.getBytes());

        channel.close();
        connection.close();
	}
}

消费者

package com.test.rabbitmq;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.ShutdownSignalException;

/**
 * @author Sirenes
 * @version 创建时间:2018年5月29日 下午11:30:09 类说明:
 */
public class Rec {
	private final static String QUEUE_NAME = "hello";

	public static void main(String[] argv)
			throws Exception {
			Rec rec1=new Rec();
			//rec1.simple();
			//rec1.work("1",100);
			//rec1.subscribe("1");
			//rec1.routing1("1");
			rec1.topic1("1");

	}
	
	
	
	public void simple() throws IOException, TimeoutException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
		// 打开连接和创建频道,与发送端一样
				ConnectionFactory factory = new ConnectionFactory();
				factory.setHost("localhost");
				Connection connection = factory.newConnection();
				Channel channel = connection.createChannel();
				// 声明队列,主要为了防止消息接收者先运行此程序,队列还不存在时创建队列。
				channel.queueDeclare(QUEUE_NAME, false, false, false, null);
				System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

				// 创建队列消费者
				QueueingConsumer consumer = new QueueingConsumer(channel);
				// 指定消费队列
				channel.basicConsume(QUEUE_NAME, true, consumer);
				while (true) {
					// nextDelivery是一个阻塞方法(内部实现其实是阻塞队列的take方法)
					QueueingConsumer.Delivery delivery = consumer.nextDelivery();
					String message = new String(delivery.getBody());
					System.out.println(" [x] Received '" + message + "'");
				}
	}
	
	public void work(String name,int time) throws Exception{
		 Connection connection = ConnectionUtil.getConnection();
	        Channel channel = connection.createChannel();
	        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

	        // 开启Qos, 同一时刻服务器只发送一条消息. 可以尝试注释该行, 会发现消息会被平均分配给两个消费者
	        channel.basicQos(1);

	        QueueingConsumer consumer = new QueueingConsumer(channel);
	        channel.basicConsume(QUEUE_NAME, false, consumer);
	        while (true) {
	            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
	            String message = new String(delivery.getBody());
	            System.out.println(name+"获取:" + message);
	            // 模拟handling
	            Thread.sleep(time);
	            // 手动确认消息接收. 在basicConsume方法中, true为自动, false为手动
	            /* 消息确认方式: 
	             * 1. 自动确认. 只要消息从队列中移除, 服务端认为消息被成功消费
	             * 2. 手动确认. 消费者获取消息后, 服务器将该消息标记为不可用, 并等待反馈. 如果消费者一直不反馈, 则该消息将一直处于不可用状态
	             */
	            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
	        }
	}
	private final static String EXCHANGE_NAME= "exchange_fanout";

	public void subscribe(String name) throws Exception {
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(name, false, false, false, null);

        // 绑定队列到交换机. 绑定也可在rabbitMQ的管理界面进行
        channel.queueBind(name, EXCHANGE_NAME, "");

        channel.basicQos(1);
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(name, false, consumer);
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(name+"获取:" + message);
            Thread.sleep(100);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
	}
	private final static String EXCHANGE_NAME1= "exchange_direct";
	public void routing1(String name) throws Exception {
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(name, false, false, false, null);
        // 绑定队列到交换机, BindingKey为 delete update
        channel.queueBind(name, EXCHANGE_NAME1, "update");
        channel.queueBind(name, EXCHANGE_NAME1, "delete");

        channel.basicQos(1);
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(name, false, consumer);

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(name+"获取:" + message);
            Thread.sleep(100);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
	}
	public void routing2(String name) throws Exception {
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(name, false, false, false, null);
        // 绑定队列到交换机, BindingKey为 delete update
        channel.queueBind(name, EXCHANGE_NAME1, "insert");
        channel.queueBind(name, EXCHANGE_NAME1, "update");
        channel.queueBind(name, EXCHANGE_NAME1, "delete");

        channel.basicQos(1);
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(name, false, consumer);

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(name+"获取:" + message);
            Thread.sleep(100);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
	}
	private final static String EXCHANGE_NAME2 = "exchange_topic";
	public void topic1(String name) throws Exception{
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(name, false, false, false, null);

        // 绑定队列到交换机
        channel.queueBind(name, EXCHANGE_NAME2, "item.update");
        channel.queueBind(name, EXCHANGE_NAME2, "item.delete");

        channel.basicQos(1);
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(name, false, consumer);
        
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println("获取:" + message);
            Thread.sleep(100);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
	}
	public void topic2(String name) throws Exception{
		Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(name, false, false, false, null);

        // 绑定队列到交换机
        channel.queueBind(name, EXCHANGE_NAME2, "item.#"); /*用通配符匹配*/

        channel.basicQos(1);
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(name, false, consumer);
        
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println("获取:" + message);
            Thread.sleep(100);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
	}
}

这里在增加一个消费者线程方便测试

package com.test.rabbitmq;


/** 
* @author Sirenes
* @version 创建时间:2018年5月30日 下午3:18:15 
* 类说明: 
*/
public class testTread {
	public static void main(String[] args) throws Exception {
		//new Rec().simple();
		//new Rec().work("2",200);
		//new Rec().subscribe("2");
		//new Rec().routing2("2");
		new Rec().topic2("2");
	}
}


到这里了解了关于Rabbit消息队列的基本模式使用,具体细节解释以及RabbitMQ整合Spring,我会在之后的文章更新。

你可能感兴趣的:(入门RabbitMQ消息队列结合SSH框架(RabbitMQ非spring封装注解篇))