利用SpringAMQP依赖使用RabbitMQ

不通过交换机情况下使用

消息消费端和提供端需要引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

都需要在application.yml进行如下配置

spring:
  rabbitmq:
    host: 192.168.230.100 #rabbitMQ的主机名
    port: 5672 #rabbitMQ的消息通信端口
    username: cyk #用户名
    password: 123 #密码
    virtual-host: / #虚拟主机(请确保消息发布端和消费端的连接参数一致,账户拥有该虚拟主机的使用权)
    listener:
      simple:
        prefetch: 1 #这条只需要消费端配置,用于限制每次拿取的信息条数,处理完才能再次拿取

消息提供端

package com.cyk.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    //如果不想在管理端手动创建队列,也可以使用下列注解自动创建队列,不过奇怪的是,这条注解运行后会导致有好多重复消息,慎用吧
    @RabbitListener(queuesToDeclare = {@Queue("simple.queue")}) 
    void contextLoads() {
        String QueueName = "simple.queue"; //队列名字(请确该队列存在)
        String message = "hello,spring amqp!"; //需要发送的消息
        rabbitTemplate.convertAndSend(QueueName,message);
    }

}

消息消费端

package com.cyk.consumer.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class SpringRabbitLIstener {

    @RabbitListener(queues = "simple.queue")
    void contextLoads(String msg) {
        System.out.println("接收到消息:"+msg);
    }
}

通过交换机情况下使用

交换机有三种,Fanout(广播),Direct(路由),Topic(话题)

Fanout

fanout就是一个最单纯的具有发布功能的交换机,可以发布给所有与其绑定的消息队列

 

在配置类进行配置,创建交换机和消息队列,并进行绑定

package com.cyk.consumer.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {

    @Bean 
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("cyk.fanout"); //创建一个名为cyk.fanout的交换机
    }

    @Bean //会根据下列方法名,创建一个消息队列
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1"); //创建一个名为fanout.queue1的交换机
    }

    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
    
    @Bean
    //将需要的交换机和消息队列进行绑定(fanoutQueue1,fanoutExchange必须与上述方法名一样)
    public Binding fanoutBinding1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }


    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }


}

消息提供端

package com.cyk.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
        String ExangeName = "cyk.fanout";
        String message = "hello,spring amqp!";
        for (int i=1;i<=1;i++){
            System.out.println(message+i);
            rabbitTemplate.convertAndSend(ExangeName,"",message+i);
        }
    }

}

消息消费端

package com.cyk.consumer.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class SpringRabbitLIstener {

    @RabbitListener(queues = "fanout.queue1")
    void ListenFanoutQueue1(String msg) throws InterruptedException {
        System.out.println("1号接收到消息:"+msg);
    }

    @RabbitListener(queues = "fanout.queue2")
    void ListenFanoutQueue2(String msg) throws InterruptedException {
        System.out.println("2号接收到消息:"+msg);
    }
}

Direct

Direct会根据交换机收到的消息中,携带的key值来判断消息的发送,只有绑定该交换机的消息队列中,具有相同key值的消息队列才会收到消息

 

消息提供端

package com.cyk.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
        String ExangeName = "cyk.direct";
        String message = "hello,spring amqp!";
        for (int i=1;i<=1;i++){
            System.out.println(message+i);
            rabbitTemplate.convertAndSend(ExangeName,"red",message+i);
        }
    }

}

消息消费端

package com.cyk.consumer.listener;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class SpringRabbitLIstener {

    //使用@RabbitListener+@QueueBinding配合,就无需像上述使用fanout交换机时一样,在配置类中一个个设置Bean,来创建交换机和消息队列
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("direct.queue1"),
            exchange = @Exchange(name = "cyk.direct",type = ExchangeTypes.DIRECT),
            key = {"red","blue"}))
    void ListenDirectQueue1(String msg) throws InterruptedException {
        System.out.println("blue队列接收到消息:"+msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("direct.queue2"),
            exchange = @Exchange(name = "cyk.direct",type = ExchangeTypes.DIRECT),
            key = {"red","yellow"}))
    void ListenDirectQueue2(String msg) throws InterruptedException {
        System.out.println("yellow队列接收到消息:"+msg);
    }
}

Topic

topic和direct交换机几乎一样,不过topic的key名是*.*的形式,还可以用#和*来代替字符,#代表0或多个单词,*代表一个单词

 

消息提供端

package com.cyk.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
        String ExangeName = "cyk.topic";
        String message = "hello,spring amqp!";
        for (int i=1;i<=1;i++){
            System.out.println(message+i);
            rabbitTemplate.convertAndSend(ExangeName,"china.news",message+i);
        }
    }

}

消息消费端

package com.cyk.consumer.listener;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class SpringRabbitLIstener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("topic.queue1"),
            exchange = @Exchange(name = "cyk.topic",type = ExchangeTypes.TOPIC),
            key = "china.#"))
    void ListenTopicQueue1(String msg) throws InterruptedException {
        System.out.println("china队列接收到消息:"+msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("topic.queue2"),
            exchange = @Exchange(name = "cyk.topic",type = ExchangeTypes.TOPIC),
            key = "#.news"))
    void ListenTopicQueue2(String msg) throws InterruptedException {
        System.out.println("news队列接收到消息:"+msg);
    }
}

消息转换器

在SpringAMQP中,消息不一定要是字符串,可以用任意类型进行传递,SpringAMQP会自动帮我们将消息进行序列化传递,但SpringAMQP是基于objectOutputStream来实现的序列化,性能和安全性都不高。我们可以采用JSON序列化方式来提高效率

 

引入依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

在配置类中声明Bean,来覆盖默认Bean

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
//这里是我懒得写类了,并不是配置类可以这样写
@Bean
public MessageConverter messageConverter(){
    return new Jackson2JsonMessageConverter();
}

直接向消息队列发送消息(接收时候注意类型一致)

package com.cyk.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class PublisherApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
        Map<String,Object> msg=new HashMap<>();
        msg.put("name","牛马");
        msg.put("age",11);
        rabbitTemplate.convertAndSend("object.queue",msg);
    }

}
posted @ 2024-03-06 19:40  凌碎瞳缘  阅读(29)  评论(0编辑  收藏  举报