Spring整合RabbitMq之精品详解

RabbitMq基础大全详解

一、创建一个项目

首先创建一个maven项目

导入spring所依赖的jar包(略)

1.导入springAMQP所依赖的jar包

 <dependency>
     <groupId>org.springframework.amqpgroupId>
     <artifactId>spring-rabbitartifactId>
     <version>1.2.0.RELEASEversion>
 dependency>

一、SpringAMQP核心组件

1、RabbitAdmin

1.1、RabbitAdmin介绍

1.声明交换机,队列,绑定等操作(也就是为RabbitTemplate的使用提供服务)

1.2、创建配置类

我们使用配置类的方式(配置类比xml格式更加直观)

注意所倒的包

RabbitConfig.java

package com.storm.config;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by StormEnum on 2019/3/22.
 */
@Configuration
public class RabbitConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses("192.168.50.129:5672");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        connectionFactory.setVirtualHost("/");
        return connectionFactory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.setAutoStartup(true);  //开启(true),否则spring容器不会加载
        return rabbitAdmin;
    }
    
}
1.3、代码展示
/**
 * Created by StormEnum on 2019/3/22.
 */
@Controller
public class RabbitController {

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @RequestMapping("test")
    @ResponseBody
    public String rabbitTest(){

        //第一种写法
        rabbitAdmin.declareExchange(new DirectExchange("rabbit.Admin.Direct.Exchange"));
        rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue"));
        rabbitAdmin.declareBinding(
                new Binding(
                    "rabbit.Admin.Queue",
                    Binding.DestinationType.QUEUE,
                    "rabbit.Admin.Direct.Exchange",
                    "rabbit.Admin.Queue",
                        new HashMap<>()
                )
        );

        //第二种写法,我看网上有人说此处不需要声明Queue和Exchange(new 出来就可以来),我感觉也是!,
        //但我没试验成功,最后我还是老老实实的声明了一下
        rabbitAdmin.declareExchange(new TopicExchange("rabbit.Admin.topic.Exchange"));
        rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue2"));
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(new Queue("rabbit.Admin.Queue2",false))
                .to(new TopicExchange("rabbit.Admin.topic.Exchange",false,false))
                .with("rabbit.#")
        );

        //注意:fanout因为没有路由规则,因此不需要 with(routing-key)

        return "那就这样吧";
    }

}

2.RabbitTemplate

2.1、RabbitTemplate介绍

1.RabbitTemplate:消息模版,
2.RabbitTemplate是RabbitMq和SpringAMQP整合时,发送消息的核心类
3.RabbitTemplate提供了丰富的发送消息方法:
   可靠性投递消息方法
   回调监听消息接口ConfirmCallback
   返回值确认接口ReturnCallback
   等······

2.2、配置类中根据connectionFactory注入RabbitTemplate
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    return rabbitTemplate;
}
2.3、代码实现
/**
 * Created by StormEnum on 2019/3/22.
 */
@Controller
public class RabbitController {

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RequestMapping("test")
    @ResponseBody
    public String rabbitTest() throws Exception{
    
        rabbitAdmin.declareExchange(new TopicExchange("rabbit.Admin.topic.Exchange"));
        rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue2"));
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(new Queue("rabbit.Admin.Queue2",false))
                .to(new TopicExchange("rabbit.Admin.topic.Exchange",false,false))
                .with("rabbit.#")
        );

       
        //根据需要设置此参数,创建一个Message,并添加额外的参数(properties)
        //在此回顾一下:message包含body和properties(properties可以不设置)
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.getHeaders().put("闫","创业");
        Message message = new Message("你好".getBytes(),messageProperties);

        //发送消息
        //rabbitTemplate.convertAndSend("rabbit.Admin.topic.Exchange", "rabbit.#", message);
        rabbitTemplate.convertAndSend("rabbit.Admin.topic.Exchange", "rabbit.someThing", message, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //在此可以添加额外的设置,也可以修改之前的设置
                System.out.println("添加额外的设置+也可以修改之前的设置");
                message.getMessageProperties().getHeaders().put("闫","添加额外的信息");
                return message;
            }
        });

        return "那就这样吧";
    }

}

看一下所发送消息:
Spring整合RabbitMq之精品详解_第1张图片

3.SimpleMessageListenerContainer

3.1、SimpleMessageListenerContainer介绍

1.简单消息监听容器
2.可以监听队列(支持多个队列)、自动启动、自动声明功能
3.可以设置事务特性、事务管理器、事务属性、事务容量、是否开启事务、消息回滚
4.可以设置消费者数量、最大最小数量、批量消费

5.设置消息确认模式、是否重回队列、异常捕获handler函数
6.设置消费者标签(deliveryTag)生成策略、是否独占模式、消费者模式等
7.设置具体的监听类、消息转换器等

8.SimpleMessageListenerContainer可以进行动态设置,比如在运行中的应用可以动态的修改其消费者的数量,接收消费的模式等

3.2、配置类中添加添加SimpleMessageListenerContainer
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    //可以监听多个队列
    container.setQueues(queue001(),queue002(),queue003());
    //当前消费者为 1 个(在SpringBoot中可以设置最大消费者数量)
    container.setConcurrentConsumers(1);
    //是否重回队列
    container.setDefaultRequeueRejected(false);
    //签收模式
    container.setAcknowledgeMode(AcknowledgeMode.AUTO);
    //监听
    container.setMessageListener(new ChannelAwareMessageListener() {
        @Override
        public void onMessage(Message message, Channel channel) throws Exception {
            String msg = new String(message.getBody());
            System.out.println("接收到的消息是--------------"+msg);
        }
    });

    return container;

}

或者使用MessageListenerAdapter自定义消息监听,使用委托类实现

@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    container.setQueues(queue001(),queue002(),queue003());
    container.setConcurrentConsumers(1);
    //是否重回队列
    container.setDefaultRequeueRejected(false);
    //签收模式
    container.setAcknowledgeMode(AcknowledgeMode.AUTO);
    
    MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //adapter.setDefaultListenerMethod("consumerListener");  对代理监听类中的默认方法进行更改
    container.setMessageListener(adapter);

    return container;
}

代理类:里面的方法名是在MessageListenerAdapter 底层定义的,参数列表也是底层定义。
当然了我们可以进行更改!

/**
 * Created by StormEnum on 2019/3/23.
 */
public class MessageDelegate {

    public void handlerMessage(byte[] messageBody){
        System.out.println("默认的方法---消息内容---------"+new String(messageBody));
    }

}

更改代理类中的默认方法:

//对代理监听类中的默认方法进行更改
adapter.setDefaultListenerMethod("consumerListener");  

那么代理类就可以设置为:

/**
 * Created by StormEnum on 2019/3/23.
 */
public class MessageDelegate {

    public void consumerListener(byte[] messageBody){
        System.out.println("默认的方法---消息内容---------"+new String(messageBody));
    }

}

更改代理类中的参数:

//对代理监听类中的参数进行更改,StringmessageConverter是我们自己创建的类
adapter.setMessageConverter(new StringMessageConverter()); 

StringmessageConverter(自己创建的一个类)
实现 MessageConverter 接口,重写MessageConverter的方法

并对StringmessageConverter 转换类进行满足自己需求的改造

/**
 * Created by StormEnum on 2019/3/23.
 */
public class StringMessageConverter implements MessageConverter {

    /**
     *TODO:java对象转换为message对象
     */
    @Override
    public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
        return new Message(object.toString().getBytes(),messageProperties);
    }

    /**
     *TODO:message对象转换为java对象
     */
    @Override
    public Object fromMessage(Message message) throws MessageConversionException {
        String contentType = message.getMessageProperties().getContentType();
        if(contentType != null && contentType.contains("消息中的参数---根据消息进行设置")){
            return new String(message.getBody());
        }
        return message.getBody();
    }
}

在SpringBoot中:我们也可以通过适配器将队列和代理类中的方法进行 一 一(yi yi)绑定

4.MessageListenerAdapter

在SimpleMessageListenerContainer中已经使用过了

5.MessageConverter

我们在发送消息的时候,正常情况下,消息是已二进制的形式进行传输的,如果期望内部帮我们转换,或者指定自定义转换器,就需要使用MessageConverter

在SimpleMessageListenerContainer中进行了简单的使用(将message对象转换为String,将String转换为message),还支持有json(内部转换),file(自定义转换)······等格式转换,

你可能感兴趣的:(消息队列,RabbitMq)