RabbitMQ对接Spring Boot

Spring AMQP

Spring AMQP 是基于 Spring 框架的AMQP消息解决方案,提供模板化的发送和接收消息的抽象层,提供基于消息驱动的 POJO的消息监听等,很大方便我们使用RabbitMQ程序的相关开发。

Spring AMQP包含一些模块,如:spring-amqp, spring-rabbit and spring-erlang等,每个模块分别由独立的一些Jar包组成.

Spring AMQP模块主要包含org.springframework.amqp.core这个包中。这个包定义的相关类主要是与前面讲的AMQP模型相对应。Spring AMQP的目的是提供不依赖于任何特定的AMQP代理实现或客户端库通用的抽象。最终用户代码将很容易实现更易替换、添加和删除AMQP,因为它可以只针对抽象层来开发。这可以很方便我们选择和使用哪一个具体的broker实现,如sping-rabbit实现。

AMQP了解参考

LINK:https://www.cnblogs.com/jmcui/p/8968315.html

LINK:https://www.cnblogs.com/wade-luffy/p/6004219.html

1.使用RabbitAdmin

maven配置:

        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <!-- 注意rabbitmq和amqp对应得版本问题-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

application.properties配置:

rabbiitmq.host =
rabbiitmq.port = 
rabbiitmq.username =
rabbiitmq.password = 
debug=true

编写RebbitMQConfig配置类:

    @Value("${rabbiitmq.host}")
    private String host;
    @Value("${rabbiitmq.port}")
    private int port;
    @Value("${rabbiitmq.username}")
    private String username;
    @Value("${rabbiitmq.password}")
    private String password;

    /**
     * @Bean("name") 注入名称必须要和获取rabbitAdmin的入参名称一致(没有尝试过初始化方式)
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost("/");
        return connectionFactory;
    }

    /**
     * 注入RabbitAdmin对象
     * @param connectionFactory 入参名称必须要和上面注入对象名称一致
     * @return
     */
    @Bean()
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        //运行服务
        rabbitAdmin.setAutoStartup(true);
        return rabbitAdmin;
    }

使用方式:


    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Test
    public void testAdmin(){
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("version","1.0");
        rabbitAdmin.declareExchange(new DirectExchange("test.direct",false,false));
        rabbitAdmin.declareExchange(new TopicExchange("test.topic",false,false));
        rabbitAdmin.declareExchange(new FanoutExchange("test.fanout",false,false));
        rabbitAdmin.declareExchange(new HeadersExchange("test.headers",false,false,arguments));

        rabbitAdmin.declareQueue(new Queue("test.direct.queue",false,false,false));
        rabbitAdmin.declareQueue(new Queue("test.topic.queue",false,false,false));
        rabbitAdmin.declareQueue(new Queue("test.fanout.queue",false,false,false));
        rabbitAdmin.declareQueue(new Queue("test.headers.queue",false,false,false,arguments));

        rabbitAdmin.declareBinding(new Binding(
                "test.direct.queue",
                Binding.DestinationType.QUEUE,
                "test.direct",
                "test.direct.#",null
        ));
        //第二种创建方式 链式创建方式-建立队列和交换机直接建立关系
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(
                        new Queue("test.direct.queue",
                                false,
                                false,
                                false,
                                null)
                ).to(
                        new DirectExchange(
                                "test.direct",
                                false,
                                false,
                                null)
                ).with("test.direct.#")
        );
        rabbitAdmin.declareBinding(new Binding(
                "test.topic.queue",
                Binding.DestinationType.QUEUE,
                "test.topic",
                "test.topic.#",null
        ));
        //第二种创建方式 链式创建方式-建立队列和交换机直接建立关系
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(
                        new Queue("test.topic.queue",
                                false,
                                false,
                                false,
                                null)
                ).to(
                        new TopicExchange(
                                "test.topic",
                                false,
                                false,
                                null)
                ).with("test.topic.#")
        );

        rabbitAdmin.declareBinding(new Binding(
                "test.fanout.queue",
                Binding.DestinationType.QUEUE,
                "test.fanout",
                "test.fanout.#",null
        ));
        //第二种创建方式 链式创建方式-建立队列和交换机直接建立关系 fanout不走路由key所以不需要with
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(
                        new Queue("test.fanout.queue",
                                false,
                                false,
                                false,
                                null)
                ).to(
                        new FanoutExchange(
                                "test.fanout",
                                false,
                                false,
                                null)
                )
        );

        rabbitAdmin.declareBinding(new Binding(
                "test.headers.queue",
                Binding.DestinationType.QUEUE,
                "test.headers",
                "test.headers.#",null
        ));
        //第二种创建方式 链式创建方式-建立队列和交换机直接建立关系 headers走得时附加参数所以写附加参数匹配规则
        rabbitAdmin.declareBinding(
                BindingBuilder.bind(
                        new Queue("test.headers.queue",
                                false,
                                false,
                                false,
                                null)
                ).to(
                        new HeadersExchange(
                                "test.headers",
                                false,
                                false,
                                null)
                ).whereAll(arguments).match()
        );
        //清空队列
        rabbitAdmin.purgeQueue("test.topic.queue",false);
    }

或者使用注解的方式 将创建注入进来

    private String queue001Name="queue001";
    private String topic001Name="topic001";
    private String queue002Name="queue002";
    private String topic002Name="topic002";
    /**
     * 可以直接用@Bean()的方式将exchange和queue以及binding直接注入到容器中RabbitmqAdmin会再启动时从容器中获取
     */
    @Bean
    public TopicExchange exchange001(){
        return new TopicExchange(topic001Name,true,false);
    }
    @Bean
    public Queue queue001(){
        return new Queue(queue001Name,false);
    }
    @Bean
    public Queue queue002(){
        return new Queue(queue002Name,false);
    }
    @Bean
    public Binding binding001() {
        String routingKey = "spring.*";
        //对象调用链
//        return BindingBuilder.bind(queue001()).to(exchange001()).with(routingKey);
        return new Binding(
                queue001Name,
                Binding.DestinationType.QUEUE,
                topic001Name,
                routingKey, null
        );
    }

2.使用RabbitMQTemplate模板的方式发送消息

在 RabbitMQAdmin 中新增 RabbitMQTemplat 配置:


    //
    @Bean
    public RabbitTemplate getRabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }

 

生产端:

    @Test
    public void testTemplate2(){
        //1.创建消息和配置消息头
        MessageProperties messageProperties = new MessageProperties();
        //设置消息转换器识别的消息类型
        messageProperties.setContentType("text/plain");
        messageProperties.getHeaders().put("type1","测试1");
        messageProperties.getHeaders().put("type2","测试2");
        messageProperties.getHeaders().put("status","等待发送中");
        Message message = new Message("消息测试1".getBytes(),messageProperties);
        System.out.println(message.getMessageProperties().getHeaders().get("status"));
        rabbitTemplate.send("topic001", "spring.abcd1", message);
        rabbitTemplate.convertAndSend("topic001", "spring.abcd2", message, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //消息再发送后得处理
                System.out.println("---------消息发送完毕--------");
                System.out.println(new String(message.getBody()));
                message.getMessageProperties().getHeaders().put("status","已发送");
                System.out.println(message.getMessageProperties().getHeaders().get("status"));
                return message;
            }
        });
    }

3.可以使用 SimpleMessageListenerContainer 消息监听容器:

在 RabbitMQTemplate  新增消息监听容器配置


    /**
     * 使用 simplemessagelistenercontainer 消息监听容器
     * 监听队列和解析消息为对象
     * @param connectionFactory
     * @return
     */
    @Bean
    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
        SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer(connectionFactory);
        //监听多个队列
        simpleMessageListenerContainer.setQueues(queue001(),queue002());
        //设置消费者数量
        simpleMessageListenerContainer.setConcurrentConsumers(1);
        //设置最多并发消费者
        simpleMessageListenerContainer.setMaxConcurrentConsumers(5);
        //是否重回队列
        simpleMessageListenerContainer.setDefaultRequeueRejected(false);
        //设置签收模式
        simpleMessageListenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
        //消费者标签(类似id)策略 用来反查消费者
        simpleMessageListenerContainer.setConsumerTagStrategy(new ConsumerTagStrategy() {
            @Override
            public String createConsumerTag(String queue) {
                System.out.println("设置消费者标签");
                return queue+"_"+ UUID.randomUUID().toString();
            }
        });
        //设置消费者
/*        simpleMessageListenerContainer.setMessageListener(new ChannelAwareMessageListener() {
            //单条消息消费
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                String messageStr = new String(message.getBody());
                System.out.println("收到消息");
                System.out.println(messageStr);
            }
        });*/
        //设置消息监听适配器
        MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(
                new MessageDelegate()
        );
        //默认调用就是handleMessage(byte[] msg)方法
        messageListenerAdapter.setDefaultListenerMethod("handleMessage2");
        //将参数转换 可以转换为java对象或者java对象转字符串
        messageListenerAdapter.setMessageConverter(new TestMessageConverter());
        //消息监听容器设置监听适配器
        simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
        return simpleMessageListenerContainer;

    }

消费监听适配器:

package com.sy.rebbitmq_spring.beans;

public class MessageDelegate {
    public void handleMessage(byte[] messageBody){
        System.out.println("默认方法:"+new String(messageBody));
    }
    public void handleMessage1(byte[] messageBody){
        System.out.println("默认方法1:"+new String(messageBody));
    }
    public void handleMessage2(String messageBody){
        System.out.println("默认方法2:"+messageBody);
    }
}

消息转换器 可以将消息转换为java对象:

package com.sy.rebbitmq_spring.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter;


public class TestMessageConverter implements MessageConverter {
    //设置转换为消息
    @Override
    public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
        return new Message(object.toString().getBytes(),messageProperties);
    }

    //**设置转换为解析
    @Override
    public Object fromMessage(Message message) throws MessageConversionException {
        String contentType = message.getMessageProperties().getContentType();
        if (contentType != null && contentType.contains("text")){
            return new String(message.getBody());
        }
        return null;
    }
}

 具体代码仓库:

GITEE LINK: https://gitee.com/suyibk/rebbitmq_spring

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值