RabbitMQ(二)Spring boot集成

RabbitMQ(二)Spring Boot集成

Spring Boot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,Spring Boot提供了spring-boot-starter-amqp项目对消息各种支持。

简单使用

1、配置pom包

主要是添加spring-boot-starter-amqp的支持

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

2、配置文件

配置rabbitmq的安装地址、端口以及账户信息

spring.application.name=rabbitmq
server.port=8080

spring.rabbitmq.host=192.168.3.253
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456

3、队列配置

package com.lay.rabbitmq.queue.config;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:36 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class RabbitConfig {
    @Bean
    public Queue queue(){
        return new Queue("hello");
    }

}

4、发送者

AmqpTemplatespringboot提供的默认实现,RabbitTemplate是对AmqpTemplate的又一次封装(两者都可以实现发送的基本功能,这里使用前者)。

package com.lay.rabbitmq.queue.sender;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:50 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
public class HelloSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send(){
        String context="hello"+new Date();
        System.out.println("Sender:"+context);
        rabbitTemplate.convertAndSend("hello",context);
    }
	
    public void send(int i){
        String context="Spring boot queue *****"+i;
        //System.out.println("Sender:"+context);
        rabbitTemplate.convertAndSend("hello",context);
    }
}

5、接收者

package com.lay.rabbitmq.queue.receiver;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:54 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {

    @RabbitHandler
    public void process(String hello){
        System.out.println("Receiver1  : " + hello);
    }

}

6、测试

package com.lay.rabbitmq;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:57 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMqHelloTest {
    @Autowired
    private HelloSender helloSender;

    @Test
    public void hello() throws Exception{
        helloSender.send();
    }

}

注意,发送者和接收者的queue name必须一致,不然不能接收

多对多使用

一个发送者,N个接收者或者N个发送者和N个接收者会出现什么情况呢?

一对多发送

对上面的代码进行了小改造,接收端注册了两个Receiver,Receiver1和Receiver2,发送端加入参数计数,接收端打印接收到的参数,下面是测试代码,发送一百条消息,来观察两个接收端的执行效果

    @Test
    public void oneToMany() throws Exception {
        for (int i=0;i<100;i++){
            helloSender.send(i);
        }
    }

结果如下:

Receiver 1: Spring boot neo queue ****** 11
Receiver 2: Spring boot neo queue ****** 12
Receiver 2: Spring boot neo queue ****** 14
Receiver 1: Spring boot neo queue ****** 13
Receiver 2: Spring boot neo queue ****** 15
Receiver 1: Spring boot neo queue ****** 16
Receiver 1: Spring boot neo queue ****** 18
Receiver 2: Spring boot neo queue ****** 17
Receiver 2: Spring boot neo queue ****** 19
Receiver 1: Spring boot neo queue ****** 20

根据返回结果得到以下结论

一个发送者,N个接受者,经过测试会均匀的将消息发送到N个接收者中

多对多发送

复制了一份发送者,加入标记,在一百个循环中相互交替发送

@Test
	public void manyToMany() throws Exception {
		for (int i=0;i<100;i++){
			helloSender.send(i);
			helloSender2.send(i);
		}
}

结果如下:

Receiver 1: Spring boot neo queue ****** 20
Receiver 2: Spring boot neo queue ****** 20
Receiver 1: Spring boot neo queue ****** 21
Receiver 2: Spring boot neo queue ****** 21
Receiver 1: Spring boot neo queue ****** 22
Receiver 2: Spring boot neo queue ****** 22
Receiver 1: Spring boot neo queue ****** 23
Receiver 2: Spring boot neo queue ****** 23
Receiver 1: Spring boot neo queue ****** 24
Receiver 2: Spring boot neo queue ****** 24
Receiver 1: Spring boot neo queue ****** 25
Receiver 2: Spring boot neo queue ****** 25

结论:和一对多一样,接收端仍然会均匀接收到消息

高级使用

对象的支持

springboot以及完美的支持对象的发送和接收,不需要格外的配置。

先定义一个用户对象User

package com.lay.rabbitmq.object.entity;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:17 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
public class User implements Serializable {
    private static final long serialVersionUID = 426370694438321946L;
    private Long id;
    private String userName;
    private String sex;
    private Integer age;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}

配置队列:

package com.lay.rabbitmq.object.config;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:36 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class RabbitObjectConfig {

    @Bean
    public Queue userQueue(){
        return new Queue("user");
    }
}

发送者:

package com.lay.rabbitmq.object.sender;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:23 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
public class UserSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send(User user){
        System.out.println("Sender User: "+user.toString());
        rabbitTemplate.convertAndSend("user",user);
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

接收者:

package com.lay.rabbitmq.object.receiver;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:25 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = "user")
public class UserReceiver {
    @RabbitHandler
    public void process(User user) {
        System.out.println("UserReceiver  : " + user.toString());
    }

}

Topic Exchange

topicRabbitMQ中最灵活的一种方式,可以根据routing_key自由的绑定不同的队列

首先对topic规则配置,这里使用两个队列来测试

队列和交换机配置

package com.lay.rabbitmq.topic.config;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 18:36 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class TopicRabbitConfig {
    public final static String message = "topic.message";
    public final static String messages = "topic.messages";
    @Bean
    public Queue queueMessage(){
        return new Queue(TopicRabbitConfig.message);
    }

    @Bean
    public Queue queueMessages(){
        return new Queue(TopicRabbitConfig.messages);
    }

    @Bean
    public TopicExchange exchange(){
        return new TopicExchange("topicExchange");
    }
    @Bean
    public Binding bindExchangeMessage(Queue queueMessage,TopicExchange exchange){
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }
    @Bean
    public Binding bindExchangeMessages(Queue queueMessages,TopicExchange exchange){
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }

}

使用queueMessages同时匹配两个队列,queueMessage只匹配”topic.message”队列

生产者:

package com.lay.rabbitmq.topic.sender;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:46 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
public class TopicSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send1(){
        String conText="this is message 1";
        System.out.println("Sender: "+conText);
        rabbitTemplate.convertAndSend("topicExchange","topic.message",conText);
    }

    public void send2(){
        String conText="this is messages 2";
        System.out.println("Sender: "+conText);
        rabbitTemplate.convertAndSend("topicExchange","topic.messages",conText);
    }
}

发送send1会匹配到topic.#和topic.message 两个Receiver都可以收到消息,发送send2只有topic.#可以匹配所有只有Receiver2监听到消息

消费者1:

package com.lay.rabbitmq.topic.receiver;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:49 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = TopicRabbitConfig.message)
public class TopicReceiver1 {
    @RabbitHandler
    public void process(String context){
        System.out.println("TopicReceiver 1: "+context);
    }
}

消费者2:

package com.lay.rabbitmq.topic.receiver;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 19:49 2018/12/18
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = TopicRabbitConfig.messages)
public class TopicReceiver2 {
    @RabbitHandler
    public void process(String context){
        System.out.println("TopicReceiver 2: "+context);
    }
}

Fanout Exchange

Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。

Fanout 相关配置

package com.lay.rabbitmq.fanout.config;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 10:13 2018/12/20
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class FanoutRabbitConfig {
    public static final String QUEUE_A = "fanout.A";
    public static final String QUEUE_B = "fanout.B";
    public static final String QUEUE_C = "fanout.C";
    public static final String FANOUT_EXCHANGE = "fanoutExchange";

    @Bean
    public Queue AMessage() {
        return new Queue(QUEUE_A);
    }

    @Bean
    public Queue BMessage() {
        return new Queue(QUEUE_B);
    }

    @Bean
    public Queue CMessage() {
        return new Queue(QUEUE_C);
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange(FANOUT_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(AMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(BMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(CMessage).to(fanoutExchange);
    }
}

这里使用了A、B、C三个队列绑定到Fanout交换机上面,发送端的routing_key写任何字符都会被忽略:

生产者:

package com.lay.rabbitmq.fanout.sender;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 13:42 2018/12/19
 * @Modified By:IntelliJ IDEA
 */
@Component
public class FanoutSender {

    @Autowired
    @Lazy
    RabbitTemplate rabbitTemplate;

    public void send(){
        String context="this is a fanout message";
        System.out.println("Sender"+context);
        rabbitTemplate.convertAndSend(FanoutRabbitConfig.FANOUT_EXCHANGE,"",context);
    }
}

消费者A:

package com.lay.rabbitmq.fanout.receiver;

import com.lay.rabbitmq.fanout.config.FanoutRabbitConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 13:44 2018/12/19
 * @Modified By:IntelliJ IDEA
 */
@Component
public class FanoutReceiverA {


    @RabbitListener(queues = FanoutRabbitConfig.QUEUE_A)
    public void process(String context){
        System.out.println("ReceiverA: "+context);
    }

    @RabbitListener(queues = FanoutRabbitConfig.QUEUE_A)
    public void process2(String context){
        System.out.println("ReceiverD: "+context);
    }
}

消费者B:

package com.lay.rabbitmq.fanout.receiver;

import com.lay.rabbitmq.fanout.config.FanoutRabbitConfig;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 13:49 2018/12/19
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = FanoutRabbitConfig.QUEUE_B)
public class FanoutReceiverB {

    @RabbitHandler
    public void process(String context){
        //System.out.println("ReceiverB: "+context);
    }
}

消费者C:

package com.lay.rabbitmq.fanout.receiver;

import com.lay.rabbitmq.fanout.config.FanoutRabbitConfig;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 13:50 2018/12/19
 * @Modified By:IntelliJ IDEA
 */
@Component
@RabbitListener(queues = FanoutRabbitConfig.QUEUE_C)
public class FanoutReceiverC {

    @RabbitHandler
    public void process(String context){
        //System.out.println("ReceiverC: "+context);
    }
}

结果绑定到fanout交换机上面的队列都收到了消息

示例代码-github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值