MessageConverter is a MessageConverter

When we send messages, normally the message body is binary data transmission. If we want to help us internally convert or specify a custom converter, we need to use MessageConverter.

Customizing a common converter: MessageConverter, generally requires implementing this interface and overriding the following two methods.

FromMessage: Message objects are converted to Java objectsCopy the code

Converter type:

Json converter: jackson2JsonMessageConverter conversion function can be Java objects DefaultJackson2JavaTypeMapper mapper, the mapping relationship to Java objects Custom binary converter: Such as image types, PDF, PPT, streaming mediaCopy the code

Code examples:

Under the code address: https://github.com/hmilyos/rabbitmqdemo.git the rabbitmq - API projectCopy the code

1. Json converter

Start by creating a Java entity Order

public class Order {

    private String id;

    private String name;

    private String content;

    public Order() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Order(String id, String name, String content) {
        this.id = id;
        this.name = name;
        this.content = content;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id='" + id + '\'' + ", name='" + name + '\'' + ", content='" + content + '\' ' +
                '} '; }}Copy the code

Then configure the jSON-supported converter in RabbitMQConfig

@ Bean / / connectionFactory are to be consistent with the top method name public SimpleMessageListenerContainer messageContainer (connectionFactory connectionFactory) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); container.setQueues(queue001(), queue002(), queue003()); / / to monitor the queue container. SetConcurrentConsumers (1); / / the number of consumers container. SetMaxConcurrentConsumers (5); / / the largest number of consumers container. SetDefaultRequeueRejected (false); / / whether or not to return to the queue container. SetAcknowledgeMode (AcknowledgeMode. AUTO); / / sign for model container. SetExposeListenerChannel (true);
        container.setConsumerTagStrategy(new ConsumerTagStrategy@override public String createConsumerTag(String queue) {return queue + "_"+ UUID.randomUUID().toString(); }}); Adapter = new MessageListenerAdapter(new MessageDelegate()); adapter.setDefaultListenerMethod("consumeMessage");
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
        adapter.setMessageConverter(jackson2JsonMessageConverter);
        container.setMessageListener(adapter);
        return container;
    }
Copy the code

In the delegate Adapter, declare the consumption method with an input parameter of Map

    public void consumeMessage(Map messageBody) {
        log.info("Map method, message content :" + messageBody);
    }
Copy the code

Write a unit test. Note that the ContentType must be JSON!!

    @Test
    public void testSendJsonMessage() throws Exception {

        Order order = new Order();
        order.setId("001");
        order.setName("Test1001 Message order");
        order.setContent("Test1001 Order Description");
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(order);
        log.info("order 4 json: "+ json); MessageProperties messageProperties = new MessageProperties(); / / here note must modify the contentType for application/json messageProperties. SetContentType ("application/json");
        Message message = new Message(json.getBytes(), messageProperties);

        rabbitTemplate.send("topic001"."spring.order", message);
    }
Copy the code

Run the unit test and the message is consumed

2. DefaultJackson2JavaTypeMapper convert Java objects

Change messageContainer to the following

@ Bean / / connectionFactory are to be consistent with the top method name public SimpleMessageListenerContainer messageContainer (connectionFactory connectionFactory) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); container.setQueues(queue001(), queue002(), queue003()); / / to monitor the queue container. SetConcurrentConsumers (1); / / the number of consumers container. SetMaxConcurrentConsumers (5); / / the largest number of consumers container. SetDefaultRequeueRejected (false); / / whether or not to return to the queue container. SetAcknowledgeMode (AcknowledgeMode. AUTO); / / sign for model container. SetExposeListenerChannel (true);
        container.setConsumerTagStrategy(new ConsumerTagStrategy@override public String createConsumerTag(String queue) {return queue + "_"+ UUID.randomUUID().toString(); }}); / / 4 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter support Java objects into the 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);
        return container;
    }
Copy the code

    public void consumeMessage(Order order) {
        log.info("Order object, message content, id:" + order.getId() +
                ", name: " + order.getName() +
                ", content: "+ order.getContent());
    }
Copy the code
    @Test
    public void testSendJavaMessage() throws Exception {
        Order order = new Order();
        order.setId("1002");
        order.setName("Test1002 message order");
        order.setContent("Test1002 Order Description");
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(order);
        log.info("order java: "+ json); MessageProperties messageProperties = new MessageProperties(); / / here note must modify the contentType for application/json messageProperties. SetContentType ("application/json"); / / note here to write your entity class path messageProperties. GetHeaders () put ("__TypeId__"."com.hmily.rabbitmqapi.spring.domain.Order");
        Message message = new Message(json.getBytes(), messageProperties);

        rabbitTemplate.send("topic001"."spring.order", message);
    }
Copy the code

Running unit tests

Error message: If you believe this class is safe to deserialize, please provide its name. If the serialization is only done by a trusted source, you can also enable trust all (*). Error message, this is because Jackson generated a security alert when converting the byte stream to a Java object.

Create a new EnableAllJackson2JavaTypeMapper class, its inheritance DefaultJackson2JavaTypeMapper this class, and then configuration allows conversion which objects here, I this is to allow all directly.

Then in just SimpleMessageListenerContainer, New EnableAllJackson2JavaTypeMapper () to the new EnableAllJackson2JavaTypeMapper (), you can.

To improve the code, convert two Java objects

public class Packaged {
    private String id;

    private String name;

    private String description;

    public Packaged() {
    }

    public Packaged(String id, String name, String description) {
        this.id = id;
        this.name = name;
        this.description = description;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Packaged{" +
                "id='" + id + '\'' + ", name='" + name + '\'' + ", description='" + description + '\' ' +
                '} '; }}Copy the code

Change messageContainer to the following

@ Bean / / connectionFactory are to be consistent with the top method name public SimpleMessageListenerContainer messageContainer (connectionFactory connectionFactory) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); container.setQueues(queue001(), queue002(), queue003()); / / to monitor the queue container. SetConcurrentConsumers (1); / / the number of consumers container. SetMaxConcurrentConsumers (5); / / the largest number of consumers container. SetDefaultRequeueRejected (false); / / whether or not to return to the queue container. SetAcknowledgeMode (AcknowledgeMode. AUTO); / / sign for model container. SetExposeListenerChannel (true);
        container.setConsumerTagStrategy(new ConsumerTagStrategy@override public String createConsumerTag(String queue) {return queue + "_"+ UUID.randomUUID().toString(); }}); / / 5 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter support Java object mapping transform the 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.hmily.rabbitmqapi.spring.domain.Order.class);
        idClassMapping.put("packaged", com.hmily.rabbitmqapi.spring.domain.Packaged.class);

        javaTypeMapper.setIdClassMapping(idClassMapping);

        jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);
        adapter.setMessageConverter(jackson2JsonMessageConverter);
        container.setMessageListener(adapter);
        return container;
    }
Copy the code

    public void consumeMessage(Packaged pack) {
        log.info("Package object, message content, id:" + pack.getId() +
                ", name: " + pack.getName() +
                ", content: "+ pack.getDescription());
    }
Copy the code
    @Test
    public void testSendMappingMessage() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Order order = new Order();
        order.setId("1001");
        order.setName("1001 Order Message");
        order.setContent("1001 Order Description");
        String json1 = mapper.writeValueAsString(order);
        log.info("order java: "+ json1); MessageProperties messageProperties1 = new MessageProperties(); / / here note must modify the contentType for 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("1002");
        pack.setName("1002 Package Message");
        pack.setDescription("1002 Package Description");
        String json2 = mapper.writeValueAsString(pack);
        log.info("pack java: "+ json2); MessageProperties messageProperties2 = new MessageProperties(); / / here note must modify the contentType for application/json messageProperties2. SetContentType ("application/json");
        messageProperties2.getHeaders().put("__TypeId__"."packaged");
        Message message2 = new Message(json2.getBytes(), messageProperties2);
        rabbitTemplate.send("topic001"."spring.pack", message2);
    }
Copy the code

Note that this is not to write the path of the class, but to write the alias

Because of junitTest, it closed as soon as it was sent, leaving one message unconsumed

3. Binary converter

Write the conversion first


public class ImageMessageConverter implements MessageConverter {

    private static final Logger log = LoggerFactory.getLogger(ImageMessageConverter.class);

	@Override
	public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
		throw new MessageConversionException(" convert error ! ");
	}

	@Override
	public Object fromMessage(Message message) throws MessageConversionException {
		log.info("-----------Image 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 = "G:/test/file/new/" + fileName + "." + extName;
		File f = new File(path);
		try {
			Files.copy(new ByteArrayInputStream(body), f.toPath());
		} catch (IOException e) {
			e.printStackTrace();
		}
		returnf; }}Copy the code

The message received

    public void consumeMessage(File file) {
        log.info(File object method, message content: + file.getName());
    }
Copy the code

Declare a global converter

@ Bean / / connectionFactory are to be consistent with the top method name public SimpleMessageListenerContainer messageContainer (connectionFactory connectionFactory) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); container.setQueues(queue001(), queue002(), queue003()); / / to monitor the queue container. SetConcurrentConsumers (1); / / the number of consumers container. SetMaxConcurrentConsumers (5); / / the largest number of consumers container. SetDefaultRequeueRejected (false); / / whether or not to return to the queue container. SetAcknowledgeMode (AcknowledgeMode. AUTO); / / sign for model container. SetExposeListenerChannel (true);
        container.setConsumerTagStrategy(new ConsumerTagStrategy@override public String createConsumerTag(String queue) {return queue + "_"+ UUID.randomUUID().toString(); }}); // 6 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;
    }
Copy the code

Write unit tests to test images

    @Test
    public void testSendExtConverterMessage() throws Exception {
        byte[] body = Files.readAllBytes(Paths.get("G:/test/file"."1001.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);
    }
Copy the code

The local folder path of the original image

Try PDF this time
public class PDFMessageConverter implements MessageConverter {

    private static final Logger log = LoggerFactory.getLogger(PDFMessageConverter.class);

	@Override
	public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
		throw new MessageConversionException(" convert error ! ");
	}

	@Override
	public Object fromMessage(Message message) throws MessageConversionException {
		log.info("-----------PDF MessageConverter----------");
		
		byte[] body = message.getBody();
		String fileName = UUID.randomUUID().toString();
		String path = "G:/test/file/new/" + fileName + ".pdf";
		File f = new File(path);
		try {
			Files.copy(new ByteArrayInputStream(body), f.toPath());
		} catch (IOException e) {
			e.printStackTrace();
		}
		returnf; }}Copy the code
    @Test
    public void testSendExtConverterMessage() throws Exception {
//        byte[] body = Files.readAllBytes(Paths.get("G:/test/file"."1001.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("G:/test/file"."AliTech101_RD.pdf"));
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setContentType("application/pdf");
        Message message = new Message(body, messageProperties);
        rabbitTemplate.send(""."pdf_queue", message);
    }
Copy the code