1. Introduction to rabbitadmin
rely on
<dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>3.6.5</version> </dependency> <!--Rabbit SpringBoot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> Here I use it directly springboot Because springboot Already spring Made a package, so I used springboot But not used springboot Related characteristics of.
Configuration class
package com.ep.rabbitmq.spring.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; /** * @author zht * @version 1.0 * @createDate 2020/06/25 14:00 */ @Configuration public class RabbitMQConfig { /**Inject rabbitMQ connection factory*/ @Bean public ConnectionFactory connectionFactory(){ CachingConnectionFactory cachingConnectionFactory=new CachingConnectionFactory(); cachingConnectionFactory.setHost("127.0.0.1:5672"); cachingConnectionFactory.setVirtualHost("/"); cachingConnectionFactory.setUsername("guest"); cachingConnectionFactory.setPassword("guest"); return cachingConnectionFactory; } @Bean public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){ RabbitAdmin rabbitAdmin=new RabbitAdmin(connectionFactory); rabbitAdmin.setAutoStartup(true); return rabbitAdmin; } }
Note: autoStartup must be set to true, otherwise the spring container will not load RabbitMQ.
Simple test
@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)) //Create a queue directly .to(new TopicExchange("test.topic", false, false)) //Directly create a switch to establish an association relationship .with("user.#")); //Specify route Key rabbitAdmin.declareBinding( BindingBuilder .bind(new Queue("test.fanout.queue", false)) .to(new FanoutExchange("test.fanout", false, false))); //Clear queue data rabbitAdmin.purgeQueue("test.topic.queue", false); }
Inject Exchange, binding, Queue
/** * Configuration for consumers * 1. Set switch type * 2. Bind queue to switch FanoutExchange: Distribute messages to all binding queues without the concept of routingkey HeadersExchange : Match by adding attribute key value DirectExchange:Distribute to the specified queue according to routingkey TopicExchange:Multi key matching */ @Bean public TopicExchange exchange001() { return new TopicExchange("topic001", true, false); } @Bean public Queue queue001() { return new Queue("queue001", true); //Queue persistence } @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); //Queue persistence } @Bean public Binding binding002() { return BindingBuilder.bind(queue002()).to(exchange002()).with("rabbit.*"); } @Bean public Queue queue003() { return new Queue("queue003", true); //Queue persistence } @Bean public Binding binding003() { return BindingBuilder.bind(queue003()).to(exchange001()).with("mq.*"); } @Bean public Queue queue_image() { return new Queue("image_queue", true); //Queue persistence } @Bean public Queue queue_pdf() { return new Queue("pdf_queue", true); //Queue persistence } }
summary
The underlying implementation of RabbitMQAdmin is to obtain the @ Bean declaration of Exchange, binding, RoutingKey and Queue from the Spring container, and then use the execution method of RabbitTemplate to execute the corresponding declaration, modification, deletion and other basic functions of RabbitMQ.
2. Message template RabbitTemplate
introduce
We have injected Exchange, Queue and binding into dependency, so how to send messages in spring? Spring provides us with RabbitTemplate, which is the message template. When we integrate with spring AMQP, we will send the key classes of messages.
This class provides a variety of sending message methods, including reliability message delivery method, callback listening message interface confirm, return value confirmation interface returncallback and so on. Again, we need to inject it into the Spring container and use it directly.
application
- Inject RabbitTemplate into configuration class
@Bean public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); return rabbitTemplate; }
- Send message test in test class
@Autowired private RabbitTemplate rabbitTemplate; @Test public void testSendMessage() throws Exception { //1 create message MessageProperties messageProperties = new MessageProperties(); messageProperties.getHeaders().put("desc", "Information description.."); messageProperties.getHeaders().put("type", "Custom message type.."); Message message = new Message("Hello RabbitMQ".getBytes(), messageProperties); rabbitTemplate.convertAndSend("topic001", "spring.amqp", message, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { System.err.println("------Add additional settings---------"); message.getMessageProperties().getHeaders().put("desc", "Information description of additional modifications"); message.getMessageProperties().getHeaders().put("attr", "Additional new properties"); return message; } }); } @Test public void testSendMessage2() throws Exception { //1 create message MessageProperties messageProperties = new MessageProperties(); messageProperties.setContentType("text/plain"); Message message = new Message("mq Message 1234".getBytes(), messageProperties); rabbitTemplate.send("topic001", "spring.abc", message); rabbitTemplate.convertAndSend("topic001", "spring.amqp", "hello object message send!"); rabbitTemplate.convertAndSend("topic002", "rabbit.abc", "hello object message send!"); } @Test public void testSendMessage4Text() throws Exception { //1 create message MessageProperties messageProperties = new MessageProperties(); messageProperties.setContentType("text/plain"); Message message = new Message("mq Message 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("Message order"); order.setContent("Description information"); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(order); System.err.println("order 4 json: " + json); MessageProperties messageProperties = new MessageProperties(); //Note that you must change the contentType to 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 message"); order.setContent("Order description"); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(order); System.err.println("order 4 json: " + json); MessageProperties messageProperties = new MessageProperties(); //Note that you must change the contentType to application/json messageProperties.setContentType("application/json"); messageProperties.getHeaders().put("__TypeId__", "com.bfxy.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 message"); order.setContent("Order description"); String json1 = mapper.writeValueAsString(order); System.err.println("order 4 json: " + json1); MessageProperties messageProperties1 = new MessageProperties(); //Note that you must change the contentType to 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("Package message"); pack.setDescription("Package description"); String json2 = mapper.writeValueAsString(pack); System.err.println("pack 4 json: " + json2); MessageProperties messageProperties2 = new MessageProperties(); //Note that you must change the contentType to 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); }
3.SimpleMessageListenerContainer
Functional features
Simple message listening container
- Set transaction characteristics, transaction manager, transaction properties, transaction capacity, whether to start transaction, rollback message, etc.
- Set the number of consumers, maximum and minimum quantity, and mass consumption
- Set message confirmation and auto confirmation mode, whether to return to the queue, exception capture handler function
- Set message confirmation and automatic confirmation mode, whether to return to the queue, and exception capture handler function.
- z set consumer label generation strategy, exclusive mode, consumer attributes, etc
- Set up specific listeners, message converters, and so on.
application
@Bean public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); //listen queue container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf()); //Current number of consumers container.setConcurrentConsumers(1); //Set maximum number of consumers container.setMaxConcurrentConsumers(5); //Set whether to return to the queue container.setDefaultRequeueRejected(false); //Set the sign in mode: automatic sign in and manual sign in (current limit and return) container.setAcknowledgeMode(AcknowledgeMode.AUTO); container.setExposeListenerChannel(true); //Set the independent label of the consumer 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("----------Consumer: "+ msg); } }); */ /** * 1 Adapter mode. By default, it has its own method name: handleMessage // You can specify the name of a method yourself: consumeMessage // You can also add a converter: convert from byte array to String MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); adapter.setDefaultListenerMethod("consumeMessage"); adapter.setMessageConverter(new TextMessageConverter()); container.setMessageListener(adapter); */ /** * 2 Adapter mode: our queue name and method name can also be matched one by one * MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); adapter.setMessageConverter(new TextMessageConverter()); Map<String, String> queueOrTagToMethodName = new HashMap<>(); queueOrTagToMethodName.put("queue001", "method1"); queueOrTagToMethodName.put("queue002", "method2"); adapter.setQueueOrTagToMethodName(queueOrTagToMethodName); container.setMessageListener(adapter); */ // 1.1 converter supporting json format /** MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); adapter.setDefaultListenerMethod("consumeMessage"); Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); adapter.setMessageConverter(jackson2JsonMessageConverter); container.setMessageListener(adapter); */ // 1.2 defaultjackson2javatypemapper & jackson2jsonmessageconverter supports java object conversion /** 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 defaultjackson 2javatypemapper & Jackson 2jsonmessageconverter supports java object multi mapping transformation /** MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); adapter.setDefaultListenerMethod("consumeMessage"); Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper(); Map<String, Class<?>> idClassMapping = new HashMap<String, Class<?>>(); idClassMapping.put("order", com.bfxy.spring.entity.Order.class); idClassMapping.put("packaged", com.bfxy.spring.entity.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"); //Global converter: ContentTypeDelegatingMessageConverter convert = new ContentTypeDelegatingMessageConverter(); TextMessageConverter textConvert = new TextMessageConverter(); convert.addDelegate("text", textConvert); convert.addDelegate("html/text", textConvert); convert.addDelegate("xml/text", textConvert); convert.addDelegate("text/plain", textConvert); Jackson2JsonMessageConverter jsonConvert = new Jackson2JsonMessageConverter(); convert.addDelegate("json", jsonConvert); convert.addDelegate("application/json", jsonConvert); ImageMessageConverter imageConverter = new ImageMessageConverter(); convert.addDelegate("image/png", imageConverter); convert.addDelegate("image", imageConverter); PDFMessageConverter pdfConverter = new PDFMessageConverter(); convert.addDelegate("application/pdf", pdfConverter); adapter.setMessageConverter(convert); container.setMessageListener(adapter); return container; }
summary
Note: SimpleMessageListenerContainer can be set dynamically. For example, in running applications, the number of consumers and the mode of receiving messages can be changed dynamically. Many customized back-end control consoles based on RabbitMQ are also set dynamically according to this feature. So we can see that spring AMQP is very powerful