Spring boot使用Rabbitmq注解及消息序列化

一、三个注解

  • @EnableRabbit
  • @RabbitListener
  • @RabbitHandler
  1. @EnableRabbit

@EnableRabbit和@Configuration一起使用,可以加在类或者方法上,这个注解开启了容器对注册的bean的@RabbitListener检查。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(RabbitBootstrapConfiguration.class)
public @interface EnableRabbit {
}

从源代码上可以看出这个注解提供了很简单的功能就是引入了另一个配置类:RabbitBootstrapConfiguration。该类注册了两个bean:一个BeanPostProcessor一个ListenerEndpointRegistry。

注册的BeanPostProcessor则会在bean初始化之后扫描@RabbitListener和@RabbitHandler注解。

@Configuration
public class RabbitBootstrapConfiguration {
 
    @Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public RabbitListenerAnnotationBeanPostProcessor rabbitListenerAnnotationProcessor() {
        return new RabbitListenerAnnotationBeanPostProcessor();
    }
 
    @Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME)
    public RabbitListenerEndpointRegistry defaultRabbitListenerEndpointRegistry() {
        return new RabbitListenerEndpointRegistry();
    }
 
}
  1. @RabbitListener

@RabbitListener用于注册Listener时使用的信息(注解声明 Binding):如queue,exchange,key、ListenerContainerFactory和RabbitAdmin的bean name。使用 @RabbitListener 注解标记方法,当监听到队列 debug 中有消息时则会进行接收并处理

@RabbitListener(bindings = @QueueBinding(
        exchange = @Exchange(value = "topic.exchange",durable = "true",type = "topic"),
        value = @Queue(value = "consumer_queue",durable = "true"),
        key = "key.#"
))
public void processMessage1(Message message) {
    System.out.println(message);
}

扫描到bean带有该注解后,首先会将注解的内容封装到Endpoint对象中并和ListenerContainerFactory的实例一起添加到上面的RabbitListenerEndpointRegistry实例中。添加的时候会创建相应的ListenerContainer实例并添加Listener对象。

RabbitListenerAnnotationBeanPostProcessor通过RabbitListenerEndpointRegistrar间接持有RabbitListenerEndpointRegistry实例。

  1. @RabbitHandler

@RabbitListener 和 @RabbitHandler结合使用,不同类型的消息使用不同的方法来处理。@RabbitListener 可以标注在类上面,需配合 @RabbitHandler 注解一起使用,@RabbitListener 标注在类上面表示当有收到消息的时候,就交给 @RabbitHandler 的方法处理,具体使用哪个方法处理,根据 MessageConverter 转换后的参数类型

@Component
@RabbitListener(queuesToDeclare = @Queue(value = "hello"))
public class HelloCustomer {
    @RabbitHandler
    public void receive1(String message){
        System.out.println("message = " + message);
    }
    @RabbitHandler
    public void receive2(byte[] message) {
        System.out.println(new String(message));
    }
}
  1. @Payload 与 @Headers
  • 使用 @Payload 和 @Headers 注解可以消息中的 body 与 headers 信息
@RabbitListener(queues = "debug")
public void processMessage1(@Payload String body, @Headers Map<String,Object> headers) {
    System.out.println("body:"+body);
    System.out.println("Headers:"+headers);
}
  • 也可以获取单个 Header 属性
@RabbitListener(queues = "debug")
public void processMessage1(@Payload String body, @Header String token) {
    System.out.println("body:"+body);
    System.out.println("token:"+token);
}

二、Message 内容对象序列化与反序列化

  • 使用 Java 序列化与反序列化
    默认的 SimpleMessageConverter 在发送消息时会将对象序列化成字节数组,若要反序列化对象,需要自定义 MessageConverter
@Configuration
public class RabbitMQConfig {

    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new MessageConverter() {
            @Override
            public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
                return null;
            }

            @Override
            public Object fromMessage(Message message) throws MessageConversionException {
                try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(message.getBody()))){
                    return (User)ois.readObject();
                }catch (Exception e){
                    e.printStackTrace();
                    return null;
                }
            }
        });

        return factory;
    }

}
@Component
@RabbitListener(queues = "consumer_queue")
public class Receiver {

    @RabbitHandler
    public void processMessage1(User user) {
        System.out.println(user.getName());
    }

}
  • 使用 JSON 序列化与反序列化

RabbitMQ 提供了 Jackson2JsonMessageConverter 来支持消息内容 JSON 序列化与反序列化消息发送者在发送消息时应设置 MessageConverter 为 Jackson2JsonMessageConverter

rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

发送消息

User user = new User("linyuan");
rabbitTemplate.convertAndSend("topic.exchange","key.1",user);

消息消费者也应配置 MessageConverter 为 Jackson2JsonMessageConverter

@Configuration
public class RabbitMQConfig {
    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;
    }
}

消费消息

@Component
@RabbitListener(queues = "consumer_queue")
public class Receiver {
    @RabbitHandler
    public void processMessage1(@Payload User user) {
        System.out.println(user.getName());
    }
}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值