• RabbitMQ消息中间件(第四章)第三部分


    本章导航

    • RabbitMQ整合Spring AMQP实战
    • RabbitMQ整合Spring Boot实战
    • RabbitMQ整合Spring Cloud实战

    RabbitMQ整合Spring AMQP实战

    • RabbitAdmin
    • SpringAMQP声明
    • SimpleMessageListenerContainer简单消息监听容器
    • MessageListenerAdapter消息监听适配器
    • MessageConverter 消息转换器,序列化和反序列化等操作
    • 注意:autoStartup必须要设置为true,否则Spring容器不会加载RabbitAdmin类
    • RabbitAdmin底层实现就是从Spring容器中获取Exchange、Bingding、RoutingKey以及Queue的@Bean声明
    • 然后使用RabbitTemplate的execute方法执行对应的声明、修改、删除等一系列RabbitMQ基础功能操作
    • 例如:添加一个交换机、删除一个绑定、清空一个队列里的消息等等

    MessageConverter

    MessageConverter消息转换器

    • 我们在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或指定自定义的转换器,就需要用到MessageConverter
    • 自定义常用转换器:MessageConverter,一般来讲都需要实现这个接口
    • 重写下面两个方法:
    • toMessage:java对象转换为Message
    • fromMessage:Message对象转换为java对象
    • Json转换器:Jackson2JsonMessageConverter:可以进行Java对象的转换功能
    • DefaultJackson2JavaTypeMapper映射器:可以进行Java对象的映射关系
    • 自定义二进制转换器:比如图片类型、PDF、PPT、流媒体
    package com.cx.temp.common.rabbitmq.spring.convert;
    
    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;
    
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.util.UUID;
    
    public class ImageMessageConverter implements MessageConverter {
    
        @Override
        public Message toMessage(Object o, MessageProperties messageProperties) throws MessageConversionException {
            throw new MessageConversionException(" convert error ! ");
        }
    
        @Override
        public Object fromMessage(Message message) throws MessageConversionException {
            System.err.println("----------------PDF MessageConverter-------------------");
    
            Object _extName = message.getMessageProperties().getHeaders().get("extName");
            String extName = _extName == null ? "png" : _extName.toString();
    
            byte[] body = message.getBody();
            String fileName = UUID.randomUUID().toString();
            String path = "d:/010_test/" + fileName + "." + extName;
            File f = new File(path);
            try {
                Files.copy(new ByteArrayInputStream(body), f.toPath());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return f;
        }
    }
    package com.cx.temp.common.rabbitmq.spring.convert;
    
    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;
    
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.util.UUID;
    
    public class PDFMessageConverter implements MessageConverter {
    
        @Override
        public Message toMessage(Object o, MessageProperties messageProperties) throws MessageConversionException {
            throw new MessageConversionException(" convert error ! ");
        }
    
        @Override
        public Object fromMessage(Message message) throws MessageConversionException {
            System.err.println("----------------PDF MessageConverter-------------------");
    
            byte[] body = message.getBody();
            String fileName = UUID.randomUUID().toString();
            String path = "d:/010_test/" + fileName + ".pdf";
            File f = new File(path);
            try {
                Files.copy(new ByteArrayInputStream(body), f.toPath());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return f;
        }
    }
    package com.cx.temp.common.rabbitmq.spring.convert;
    
    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 TextMessageConverter implements MessageConverter {
    
        @Override
        public Message toMessage(Object o, MessageProperties messageProperties) throws MessageConversionException {
            return new Message(o.toString().getBytes(), messageProperties);
        }
    
        @Override
        public Object fromMessage(Message message) throws MessageConversionException {
            String contentType = message.getMessageProperties().getContentType();
            if(null != contentType && contentType.contains("text")) {
                return new String(message.getBody());
            }
            return message.getBody();
        }
    
    }
    package com.cx.temp.common.rabbitmq.spring;
    
    import com.cx.temp.common.rabbitmq.spring.adapter.MessageDelegate;
    import com.cx.temp.common.rabbitmq.spring.convert.ImageMessageConverter;
    import com.cx.temp.common.rabbitmq.spring.convert.PDFMessageConverter;
    import com.cx.temp.common.rabbitmq.spring.convert.TextMessageConverter;
    import com.cx.temp.common.rabbitmq.spring.entity.Order;
    import com.cx.temp.common.rabbitmq.spring.entity.Packaged;
    import com.rabbitmq.client.Channel;
    import org.springframework.amqp.core.*;
    import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
    import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
    import org.springframework.amqp.rabbit.core.RabbitAdmin;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
    import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
    import org.springframework.amqp.support.ConsumerTagStrategy;
    import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
    import org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper;
    import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    /**
     *
     */
    @Configuration
    @ComponentScan({"com.cx.temp.*"})
    public class RabbitMQConfig {
    
        @Bean
        public ConnectionFactory connectionFactory() {
            CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
            connectionFactory.setAddresses("127.0.0.1:5672");
            connectionFactory.setUsername("root");
            connectionFactory.setPassword("123456");
            connectionFactory.setVirtualHost("/test001");
            return connectionFactory;
        }
    
        public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
            RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
            rabbitAdmin.setAutoStartup(true);
            return rabbitAdmin;
        }
    
        /**
         * 针对消费者配置
         * 1.设置交换机类型
         * 2.将队列绑定到交换机
         * FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
         * HeadersExchange: 通过添加属性key-value匹配
         * DirectExchange: 按照routingkey分发到指定队列
         * TopicExchange: 多关键字匹配
         *
         * @return
         */
        @Bean
        public TopicExchange exchange001() {
            return new TopicExchange("topic001", true, false);
        }
    
        @Bean
        public Queue queue001() {
            return new Queue("queue001", true); //队列持久
        }
    
        @Bean
        public Binding binding001() {
            return BindingBuilder.bind(queue001()).to(exchange001()).with("spring.*");
        }
    
        @Bean
        public TopicExchange exchange002() {
            return new TopicExchange("topic002", true, false);
        }
    
        @Bean
        public Queue queue002() {
            return new Queue("queue002", true); //队列持久
        }
    
        @Bean
        public Queue queue003() {
            return new Queue("queue003", true); //队列持久
        }
    
        @Bean
        public Binding binding002() {
            return BindingBuilder.bind(queue002()).to(exchange002()).with("rabbit.*");
        }
    
        @Bean
        public Binding binding003() {
            return BindingBuilder.bind(queue003()).to(exchange001()).with("mq.*");
        }
    
        @Bean
        public Queue queue_image() {
            return new Queue("image_queue", true); //队列持久
        }
    
        @Bean
        public Queue queue_pdf() {
            return new Queue("pdf_queue", true); //队列持久
        }
    
        @Bean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
            return rabbitTemplate;
        }
    
        @Bean
        public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
    
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
            container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf());
            container.setConcurrentConsumers(1);
            container.setMaxConcurrentConsumers(5);
            container.setDefaultRequeueRejected(false); //不进行重回队列
            container.setAcknowledgeMode(AcknowledgeMode.AUTO); //自动签收机制
            container.setConsumerTagStrategy(new ConsumerTagStrategy() {
                @Override
                public String createConsumerTag(String queue) {
                    return queue + "_" + UUID.randomUUID().toString();
                }
            });
    //        container.setMessageListener(new ChannelAwareMessageListener() {
    //            @Override
    //            public void onMessage(Message message, Channel channel) throws Exception {
    //                String msg = new String(message.getBody());
    //                System.err.println("-----------消费者:" + msg);
    //            }
    //        });
    
    
            //第一种
    //        MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //        container.setMessageListener(adapter);
    
            //第二种
    //        MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //        adapter.setDefaultListenerMethod("consumeMessage"); //也可以通过这个方法设置默认查找适配器对象的方法,默认的方法名是handleMessage
    
            //第三种
            /** 1.适配器方式,默认是有自己的方法名称的:handleMessage
             //可以自己指定一个方法的名字:consumeMessage
             //也可以添加一个转换器:从字节数组转换String
             MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
             adapter.setDefaultListenerMethod("consumeMessage");
             adapter.setMessageConverter(new TextMessageConverter());
             container.setMessageListener(adapter);
             */
    
            /**
             * 2.适配器方式:我们的队列名称和方法名称也可以也进行一一匹配
             */
    //        Map<String, String> queueOrTagToMethodName = new HashMap<>();
    //        queueOrTagToMethodName.put("queue001", "method1");
    //        queueOrTagToMethodName.put("queue002", "method2");
    //
    //        MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //        adapter.setQueueOrTagToMethodName(queueOrTagToMethodName);
    //        adapter.setMessageConverter(new TextMessageConverter());
    //        container.setMessageListener(adapter);
    
              // 1.1 支持JSON格式的转换器
    //        MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //        adapter.setDefaultListenerMethod("consumeMessage");
    //        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    //        adapter.setMessageConverter(jackson2JsonMessageConverter);
    //        container.setMessageListener(adapter);
    
              // 1.2 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持Java对象转换
    //          MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //          adapter.setDefaultListenerMethod("consumeMessage");
    //          Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    //          DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper();
    //          jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);
    //          adapter.setMessageConverter(jackson2JsonMessageConverter);
    //          container.setMessageListener(adapter);
    
              // 1.3 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持Java对象多映射转换
    //          MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
    //          adapter.setDefaultListenerMethod("consumeMessage");
    //          Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    //          DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper();
    //
    //          Map<String, Class<?>> idClassMapping = new HashMap<>();
    //          idClassMapping.put("order", Order.class);
    //          idClassMapping.put("packaged", Packaged.class);
    //          javaTypeMapper.setIdClassMapping(idClassMapping);
    //          jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);
    //          adapter.setMessageConverter(jackson2JsonMessageConverter);
    //          container.setMessageListener(adapter);
    
              //1.4 ext convert
            MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
            adapter.setDefaultListenerMethod("consumeMessage");
    
            //全局转换器:
            ContentTypeDelegatingMessageConverter convert = new ContentTypeDelegatingMessageConverter();
            TextMessageConverter textMessageConverter = new TextMessageConverter();
            convert.addDelegate("text",  textMessageConverter);
            convert.addDelegate("html/text",  textMessageConverter);
            convert.addDelegate("xml/text",  textMessageConverter);
            convert.addDelegate("text/plan",  textMessageConverter);
    
            Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
            convert.addDelegate("json",  jackson2JsonMessageConverter);
            convert.addDelegate("application/json",  jackson2JsonMessageConverter);
    
            ImageMessageConverter imageMessageConverter = new ImageMessageConverter();
            convert.addDelegate("image/png",  imageMessageConverter);
            convert.addDelegate("image",  imageMessageConverter);
    
            PDFMessageConverter pdfMessageConverter = new PDFMessageConverter();
            convert.addDelegate("application/pdf",  pdfMessageConverter);
    
            adapter.setMessageConverter(convert);
            container.setMessageListener(adapter);
    
             return container;
        }
    
    
    }

      

    package com.cx.temp.rabbitmq;
    
    import com.cx.temp.admin.AdminApplication;
    import com.cx.temp.common.rabbitmq.spring.entity.Order;
    import com.cx.temp.common.rabbitmq.spring.entity.Packaged;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.amqp.AmqpException;
    import org.springframework.amqp.core.*;
    import org.springframework.amqp.rabbit.core.RabbitAdmin;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.io.File;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.HashMap;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = AdminApplication.class)
    public class RabbitMQTest {
    
        @Autowired
        private RabbitAdmin rabbitAdmin;
    
        @Test
        public void testAdmin() throws Exception {
    
            //第一种声明与绑定方式
            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.declareQueue(new Queue("test.direct.queue", false));
    
            rabbitAdmin.declareQueue(new Queue("test.topic.queue", false));
    
            rabbitAdmin.declareQueue(new Queue("test.fanout.queue", false));
    
            rabbitAdmin.declareBinding(new Binding("test.direct.queue", Binding.DestinationType.QUEUE,
                    "test.direct", "direct", new HashMap<>()));
    
            //第二种 支持链式声明与绑定
            rabbitAdmin.declareBinding(BindingBuilder
                    .bind(new Queue("test.topic.queue", false))
                    .to(new TopicExchange("test.topic", false, false))
                    .with("user.#"));
    
            rabbitAdmin.declareBinding(BindingBuilder
                    .bind(new Queue("test.fanout.queue", false))
                    .to(new FanoutExchange("test.fanout", false, false)));
    
    
            //清空队列数据
            rabbitAdmin.purgeQueue("test.topic.queue", false);
    
        }
    
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        @Test
        public void testSendMessage() throws Exception {
            //1 创建消息
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.getHeaders().put("desc", "信息描述..");
            messageProperties.getHeaders().put("type", "自定义消息类型..");
            Message message = new Message("Hello RabbitMQ".getBytes(), messageProperties);
    
            rabbitTemplate.convertAndSend("topic001", "spring.amqp", message, new MessagePostProcessor() {
                //消息发送之后在对这个message进行设置
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    System.err.println("----------添加额外的设置-----------");
                    message.getMessageProperties().getHeaders().put("desc", "额外修改的信息描述");
                    message.getMessageProperties().getHeaders().put("attr", "额外新加的属性");
                    return message;
                }
            });
    
        }
    
        @Test
        public void testSendMessage2() throws Exception {
            //1 创建消息
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setContentType("text/plain");
            Message message = new Message("mq 消息1234".getBytes(), messageProperties);
    
            rabbitTemplate.send("topic001", "spring.abc",message);
    
            rabbitTemplate.convertAndSend("topic001", "spring.amqp", "hello object message send!");
            rabbitTemplate.convertAndSend("topic002", "rabbit.amqp", "hello object message send!");
    
        }
    
        @Test
        public void testSendMessage4Text() throws Exception {
            //1 创建消息
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setContentType("text/plain");
            Message message = new Message("mq 消息1234".getBytes(), messageProperties);
    
            rabbitTemplate.send("topic001", "spring.abc",message);
            rabbitTemplate.send("topic002", "rabbit.abc",message);
        }
    
        @Test
        public void testSendJsonMessage() throws Exception {
            Order order = new Order();
            order.setId("001");
            order.setName("消息订单");
            order.setContent("描述信息");
    
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(order);
    
            System.err.println("order 4 json" + json);
    
            MessageProperties messageProperties = new MessageProperties();
            //这里注意一定要修改contentType为application/json
            messageProperties.setContentType("application/json");
    
            Message message = new Message(json.getBytes(), messageProperties);
    
            rabbitTemplate.send("topic001", "spring.order",message);
        }
    
        @Test
        public void testSendJavaMessage() throws Exception {
            Order order = new Order();
            order.setId("001");
            order.setName("消息订单");
            order.setContent("描述信息");
    
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(order);
    
            System.err.println("order 4 json" + json);
    
            MessageProperties messageProperties = new MessageProperties();
            //这里注意一定要修改contentType为application/json
            messageProperties.setContentType("application/json");
            messageProperties.getHeaders().put("__TypeId__", "com.cx.temp.common.rabbitmq.spring.entity.Order");
    
            Message message = new Message(json.getBytes(), messageProperties);
    
            rabbitTemplate.send("topic001", "spring.order",message);
        }
    
        @Test
        public void testSendMappingMessage() throws Exception {
    
            ObjectMapper mapper = new ObjectMapper();
    
            Order order = new Order();
            order.setId("001");
            order.setName("消息订单");
            order.setContent("描述信息");
    
            String json1 = mapper.writeValueAsString(order);
            System.err.println("order 4 json" + json1);
    
            MessageProperties messageProperties1 = new MessageProperties();
            //这里注意一定要修改contentType为application/json
            messageProperties1.setContentType("application/json");
            messageProperties1.getHeaders().put("__TypeId__", "order");
    
            Message message1 = new Message(json1.getBytes(), messageProperties1);
    
            rabbitTemplate.send("topic001", "spring.order", message1);
    
            Packaged pack = new Packaged();
            pack.setId("002");
            pack.setName("包裹消息");
            pack.setDescription("包裹描述消息");
    
            String json2 = mapper.writeValueAsString(pack);
            System.err.println("pack 4 json" + json2);
    
            MessageProperties messageProperties2 = new MessageProperties();
            //这里注意一定要修改contentType为application/json
            messageProperties2.setContentType("application/json");
            messageProperties2.getHeaders().put("__TypeId__", "packaged");
    
            Message message2 = new Message(json2.getBytes(), messageProperties2);
    
            rabbitTemplate.send("topic001", "spring.pack", message2);
        }
    
      @Test
    public void testSendExtConverterMessage() throws Exception { byte[] body = Files.readAllBytes(Paths.get("d://002_books", "picture.png")); MessageProperties messageProperties = new MessageProperties(); messageProperties.setContentType("image/png"); messageProperties.getHeaders().put("extName", "png"); Message message = new Message(body, messageProperties); rabbitTemplate.send("", "image_queue",message); // byte[] body = Files.readAllBytes(Paths.get("d://002_books", "mysql.pdf")); // MessageProperties messageProperties = new MessageProperties(); // messageProperties.setContentType("application/pdf"); // // Message message = new Message(body, messageProperties); // // rabbitTemplate.send("", "pdf_queue",message); } }
  • 相关阅读:
    腾讯创业专题
    SP的新出路:亿美软通瞄准移动商务
    全球移动支付发展现状移动支付之综述篇
    C#开发终端式短信的原理和方法
    Windows CE的学习路线
    Linux Crontab 定时任务
    linux的中文man帮助
    PHP 变量与数组
    写商业计划书的几点心得 汉理资本钱学峰
    用PHP输出静态页面的两种方法
  • 原文地址:https://www.cnblogs.com/huihui-hui/p/14400096.html
Copyright © 2020-2023  润新知