Spring AMQP:MessageListenerAdapter MessageConverter
一.MessageListenerAdapter
消息监听适配器
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Bean public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){ SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); //设置监听的队列 container.setQueues(queue()); //设置当前消费者数量 container.setConcurrentConsumers( 1 ); container.setMaxConcurrentConsumers( 5 ); //重回队列 container.setDefaultRequeueRejected( false ); //签收机制 container.setAcknowledgeMode(AcknowledgeMode.AUTO); //消费端标签策略 container.setConsumerTagStrategy(queue-> queue+ "_" + UUID.randomUUID().toString()); //消息适配器 MessageListenerAdapter adapter = new MessageListenerAdapter( new MessageDelegate()); container.setMessageListener(adapter); return container; } |
1 | MessageDelegate类: |
1 2 3 4 5 6 7 8 9 10 | public class MessageDelegate { public void handleMessage( byte [] messageBody){ System.out.println( "默认方法,消息:" + new String(messageBody)); } public void handleMessage(String messageBody){ System.out.println( "字符串方法,消息" +messageBody); } } |
注意,自定义的Delegate类,默认方法名是handlermessage
当然,想自定义方法名,可以setDefaultListenerMethod(),这里不再演示。
测试字符串:
1 2 3 4 | @Test public void testSend1(){ rabbitTemplate.convertAndSend( "amqp.bean.topic" , "amqp.send" , "hello spring" ); } |
测试字节数组:
1 2 3 4 | @Test public void testSend2(){ rabbitTemplate.convertAndSend( "amqp.bean.topic" , "amqp.send" , "hello spring2" .getBytes()); } |
此外也可以自定义转换器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class MyMessageConvert implements MessageConverter { /** * java对象转换为Message对象 */ @Override public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { return new Message(object.toString().getBytes(),messageProperties); } /** * message对象转换为java对象 */ @Override public Object fromMessage(Message message) throws MessageConversionException { return new String(message.getBody()); } } |
在适配器中配置转换器
1 2 3 4 | //消息适配器 MessageListenerAdapter adapter = new MessageListenerAdapter( new MessageDelegate()); adapter.setMessageConverter( new MyMessageConvert()); container.setMessageListener(adapter); |
配置了消息转换器后,现在无论发送的消息是字符串还是字节数组,适配器都直接进入handleMessage(String messageBody)方法。
适配器还可以将队列名称与方法名称进行一一匹配。
需要传入一个map,key是队列名,value是方法名
1 | adapter.setQueueOrTagToMethodName(queueName,method); |
源码:
1 2 3 4 5 6 7 8 9 10 11 | /** * Set the mapping of queue name or consumer tag to method name. The first lookup * is by queue name, if that returns null, we lookup by consumer tag, if that * returns null, the {@link #setDefaultListenerMethod(String) defaultListenerMethod} * is used. * @param queueOrTagToMethodName the map. * @since 1.5 */ public void setQueueOrTagToMethodName(Map<String, String> queueOrTagToMethodName) { this .queueOrTagToMethodName.putAll(queueOrTagToMethodName); } |
当队列与方法绑定后,队列里的消息会被绑定的方法所处理。
二.MessageConverter
消息转换器,一般自定义转换器需要实现这个接口,重写toMessage和fromMessage方法。
Json转换器:Jackson2JsonMessageConverter,可以进行java对象的转换功能
先加上jackson依赖:
1 2 3 4 5 6 7 8 9 10 11 | <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version> 2.9 . 9 </version> </dependency> <!-- https: //mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version> 2.9 . 9 </version> </dependency> |
json测试:
在delegate类中定义处理json的方法:
1 2 3 | public void handleMessage(Map messageBody){ System.out.println( "json转换,消息:" +messageBody); } |
在adapter中配置Jackson2JsonMessageConverter
1 2 3 4 5 6 7 | //消息适配器 MessageListenerAdapter adapter = new MessageListenerAdapter( new MessageDelegate()); //adapter.setMessageConverter(new MyMessageConvert()); //json形式转换器 Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); adapter.setMessageConverter(converter); container.setMessageListener(adapter); |
测试发送消息:
1 2 3 4 5 6 7 8 9 10 | @Test public void testJson() throws JsonProcessingException { User user = new User( "张三" , 22 ); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); MessageProperties properties = new MessageProperties(); properties.setContentType( "application/json" ); Message message = new Message(json.getBytes(), properties); rabbitTemplate.send( "amqp.bean.topic" , "amqp.send" ,message); } |
测试结果:
配置DefaultJackson2JavaTypeMapper映射器:进行java对象的映射关系
1 2 3 4 5 6 7 8 9 10 11 | //消息适配器 MessageListenerAdapter adapter = new MessageListenerAdapter( new MessageDelegate()); //adapter.setMessageConverter(new MyMessageConvert()); //json形式转换器 Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); DefaultJackson2JavaTypeMapper mapper = new DefaultJackson2JavaTypeMapper(); //设置安全包 mapper.setTrustedPackages( "com.wj.springamqp.domain" ); converter.setJavaTypeMapper(mapper); adapter.setMessageConverter(converter); container.setMessageListener(adapter); |
注意要setTrustedPackages,否则会报如下错误。
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Test public void testJson() throws JsonProcessingException { User user = new User( "张三" , 22 ); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); MessageProperties properties = new MessageProperties(); properties.setContentType( "application/json" ); //key:_TypeId_ value:类的全路径 //加上去后,就可以支持json转换为java对象 properties.getHeaders().put( "__TypeId__" , "com.wj.springamqp.domain.User" ); Message message = new Message(json.getBytes(), properties); rabbitTemplate.send( "amqp.bean.topic" , "amqp.send" ,message); } |
注意!!!"__TypeId__"这里下划线是四个,前面两个后面两个,不然无法转为java对象。
Jackson2JsonMessageConverter和DefaultJackson2JavaTypeMapper支持java对象多映射转换。
1 2 3 4 5 6 7 8 9 10 11 12 | //json形式转换器 Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); DefaultJackson2JavaTypeMapper mapper = new DefaultJackson2JavaTypeMapper(); //设置安全包 mapper.setTrustedPackages( "com.wj.springamqp.domain" ); Map<String, Class<?>> map = new HashMap<>(); map.put( "user" , com.wj.springamqp.domain.User. class ); map.put( "stu" , com.wj.springamqp.domain.Stu. class ); mapper.setIdClassMapping(map); converter.setJavaTypeMapper(mapper); |
此外MessageConverter支持pdf,image的转换,在发送消息的时候,需要将文件转换为二进制字节流,然后在转换器中生成文件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix