springboot集成RabbitMQ

springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了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.rabbitmq.host=192.168.0.86
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true

spring.rabbitmq.template.mandatory=true

3.队列配置(生产端、消费端都需要此配置)

@Configuration

public class RabbitConfig {

 //hello是队列的名称。可以定义多个队列

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

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

}

3、发送者(字符串

rabbitTemplate是springboot 提供的默认实现

public class HelloSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;
    public void send() {
        String context = "hello " + new Date();
        this.rabbitTemplate.convertAndSend("hello", context);  //第一个参数是队列,第二个参数是信息。可以使字符串或者对象
    }

}

4、接收者 注意RabbitListener在方法上

@Component
public class HelloReceiver {
    @RabbitListener(queues = "hello")
    @RabbitHandler
    public void process(String hello) {
        System.out.println("Receiver  : " + hello);
    }

    @RabbitListener(queues = "world")
    @RabbitHandler
    public void process(String world){
        System.out.println("Receiver  : " + world
    }

}

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

5. 对象的支持

//发送者
public void send(User user) {
    System.out.println("Sender object: " + user.toString());
    this.rabbitTemplate.convertAndSend("object", user); //object 是队列名称
}


//接受者
@RabbitListener(queues = "object")
@RabbitHandler
public void process(User user) {
    System.out.println("Receiver object : " + user);

}

6. Topic Exchange

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

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

1> 配置类:

@Configuration
public class TopicRabbitConfig {
    final static String message = "topic.message";

    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
    TopicExchange exchange() {
        return new TopicExchange("exchange");
    }

    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }

    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }

}

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

2> 发送

public void send1() {

    String context = "hi, i am message 1";
    System.out.println("Sender : " + context);
    this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
}

public void send2() {
    String context = "hi, i am messages 2";
    System.out.println("Sender : " + context);
    this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);

}

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

7. Fanout Exchange

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

1> 配置类

@Configuration
public class FanoutRabbitConfig {

    @Bean
    public Queue AMessage() {
        return new Queue("fanout.A");
    }

    @Bean
    public Queue BMessage() {
        return new Queue("fanout.B");
    }

    @Bean
    public Queue CMessage() {
        return new Queue("fanout.C");
    }

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

    @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写任何字符都会被忽略:

public void send() {
        String context = "hi, fanout msg ";
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("fanoutExchange","", context);

}

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

8. 传对象的情况的优化

使用上面的方式传的对象的问题:

1. 生产者的对象A 和消费者的对象B 必须完全一样,在同一个包里面,里面的字段也一样,一旦改了对象里面的属性,就会出错

2. web界面上,显示的消息是乱码

如何解决以上的问题??

将对象转成json字符串....

手动新增了转化

在配置文件中加上:

@Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        return template;
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;

    }

然后在生产和消费信息的地方使用他们:

@RabbitListener(queues = "merchant", containerFactory="rabbitListenerContainerFactory")
public void process(@Payload UpdateMerchant request) { 
     UpdateMerchantResponse response = new UpdateMerchantResponse();
    logger.info(request.getMerchantId() + "->" + response.getReturnCode());
 }
就可以啦

猜你喜欢

转载自blog.csdn.net/zhuchunyan_aijia/article/details/80242356