RabbitMQ(二)Java基本应用

本文介绍了一个基于RabbitMQ实现的消息生产者与消费者的Java示例代码,演示了五种不同的交换机类型:默认、扇形(Fanout)、直接(Direct)、头信息(Headers)和主题(Topic)。每种类型展示了如何配置队列、交换机及绑定,以及消息的发送和接收。

消息生产者代码

public class Send {
    public final static String QUEUE_NAME = "com.lyyz.queue";
    public final static String EXCHANGE_NAME = "com.lyyz.exchange";
    public final static String ROUTINGKEY_NAME = "com.lyyz.routingKey";
    //DEFAULT, DIRECT, TOPIC, HEADERS, FANOUT
    public final static String EXCHANGE_TYPE = "TOPIC";
    public static String message = "Hello World!";
    private static Scanner scanner = new Scanner(System.in);
    private static boolean sysIn() {
        message = scanner.nextLine();
        if (message.length() == 0) return false;
        return true;
    }
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setUsername("root");
        factory.setPassword("root");
        factory.setVirtualHost("/");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        switch(EXCHANGE_TYPE){
            case("DEFAULT")://默认,向指定的队列发送消息,消息只会被一个consumer处理,多个消费者消息会轮训处理,消息发送时如果没有consumer,消息不会丢失
                //为消息通道绑定一个队列
                //队列的相关参数需要与第一次定义该队列时相同,否则会出错
                //参数1:队列名称
                //参数2:为true时server重启队列不会消失
                //参数3:队列是否是独占的,如果为true只能被一个connection使用,其他连接建立时会抛出异常
                //参数4:队列不再使用时是否自动删除(没有连接,并且没有未处理的消息)
                //参数5:建立队列时的其他参数
                channel.queueDeclare(QUEUE_NAME, false, false, false, null);
                while(sysIn()){
                    //向server发布一条消息
                    //参数1:exchange名字,若为空则使用默认的exchange
                    //参数2:routing key
                    //参数3:其他的属性
                    //参数4:消息体
                    //RabbitMQ默认有一个exchange,叫default exchange,它用一个空字符串表示,它是direct exchange类型,
                    //任何发往这个exchange的消息都会被路由到routing key的名字对应的队列上,如果没有对应的队列,则消息会被丢弃
                    channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
                    System.out.println(" [x] Sent '" + message + "'");
                }
                break;
            case("FANOUT"):
                //广播给所有队列  接收方也必须通过fanout交换机获取消息,所有连接到该交换机的consumer均可获取消息
                //如果producer在发布消息时没有consumer在监听,消息将被丢弃


                //定义一个交换机
                //参数1:交换机名称
                //参数2:交换机类型
                //参数3:交换机持久性,如果为true则服务器重启时不会丢失
                //参数4:交换机在不被使用时是否删除
                //参数5:交换机的其他属性
                channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
                while(sysIn()){
                    channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
                    System.out.println(" [x] Sent '" + message + "'");
                }
                break;
            case("DIRECT"):
                //向所有绑定了相应routing key的队列发送消息
                //如果producer在发布消息时没有consumer在监听,消息将被丢弃
                //如果有多个consumer监听了相同的routing key  则他们都会受到消息
                channel.exchangeDeclare(EXCHANGE_NAME,"direct");
                while(sysIn()){
                    channel.basicPublish(EXCHANGE_NAME, ROUTINGKEY_NAME, null, message.getBytes());
                    System.out.println(" [x] Sent '" + message + "'");
                }
                break;
            case("HEADERS"):
                //与topic和direct有一定相似之处,但不是通过routing key来路由消息
                //通过headers中词的匹配来进行路由
                channel.exchangeDeclare(EXCHANGE_NAME, "headers");
                while(sysIn()){
                    Map<String, Object> headers = new HashMap<String, Object>();
                    headers.put("key", "key"); //定义headers
                    AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder().headers(headers);
                    channel.basicPublish(EXCHANGE_NAME, ROUTINGKEY_NAME, builder.build(), message.getBytes());
                    System.out.println(" [x] Sent '" + message + "'");
                }
                break;
            case("TOPIC"):
                //与direct模式有类似之处,都使用routing key作为路由
                //不同之处在于direct模式只能指定固定的字符串,而topic可以指定一个字符串模式
                channel.exchangeDeclare(EXCHANGE_NAME,"topic");
                while(sysIn()){
                    channel.basicPublish(EXCHANGE_NAME, ROUTINGKEY_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
                    System.out.println(" [x] Sent '" + message + "'");
                }
                break;
            default:

        }
        //关闭通道和连接
        channel.close();
        connection.close();
    }
}

消息消费者代码

public class Recv1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setUsername("root");
        factory.setPassword("root");
        factory.setVirtualHost("/");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        String queueName = "";
        switch(Send.EXCHANGE_TYPE){
            case("DEFAULT"):
                //默认情况 直接声明队列
                channel.queueDeclare(Send.QUEUE_NAME, false, false, false, null);
                System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
                queueName = Send.QUEUE_NAME;
                break;
            case("FANOUT"):
                //声明 交换机
                channel.exchangeDeclare(Send.EXCHANGE_NAME,"fanout");
                //声明一个临时队列,该队列会在使用完比后自动销毁
                queueName = channel.queueDeclare().getQueue();
                //将队列绑定到交换机,参数3无意义此时
                channel.queueBind(queueName,Send.EXCHANGE_NAME,"");
                System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
                break;
            case("DIRECT"):
                channel.exchangeDeclare(Send.EXCHANGE_NAME,"direct");
                queueName = channel.queueDeclare().getQueue();
                //将队列绑定到交换机,根据routingkey参数绑定
                channel.queueBind(queueName,Send.EXCHANGE_NAME,Send.ROUTINGKEY_NAME);
                System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
                break;
            case("HEADERS"):
                channel.exchangeDeclare(Send.EXCHANGE_NAME,"headers");
                queueName = channel.queueDeclare().getQueue();
                Map<String, Object> headers = new HashMap<String, Object>();
                headers.put("key", "key1"); //定义headers
                headers.put("x-match", "any");//all==匹配所有条件,any==匹配任意条件
                //将队列绑定到交换机,根据headers参数绑定
                channel.queueBind(queueName,Send.EXCHANGE_NAME,Send.ROUTINGKEY_NAME,headers);
                System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
                break;
            case("TOPIC"):
                channel.exchangeDeclare(Send.EXCHANGE_NAME,"topic");
                queueName = channel.queueDeclare().getQueue();
                //监听两种模式 #匹配一个或多个单词 *匹配一个单词
                channel.queueBind(queueName,Send.EXCHANGE_NAME,"com.#");
                channel.queueBind(queueName,Send.EXCHANGE_NAME,"com.lyyz.*");
                System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
                break;
            default:
        }



        //定义一个消费者  接收消息
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            }
        };
        // 在同一时间不要给一个worker一个以上的消息。
        // 不要将一个新的消息分发给worker知道它处理完了并且返回了前一个消息的通知标志(acknowledged)
        // 替代的,消息将会分发给下一个不忙的worker。
        channel.basicQos(1); //server push消息时的队列长度
        //为channel声明一个consumer,服务器会推送消息
        //参数1:队列名称
        //参数2:是否发送ack包,不发送ack消息会持续在服务端保存,直到收到ack。  可以通过channel.basicAck手动回复ack
        //参数3:消费者
        channel.basicConsume(queueName, true, consumer);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值