Spring AMQP基本API

Spring AMQP基本API

1. RabbitTemplate【发接消息】

RabbitTemplate 是 Spring AMQP 的核心 API,用于发送和接收消息。它提供了多种方法来发送消息到指定的交换机和路由键。

  • 发送消息:将消息发送到指定的交换机和路由键。
  • 接收消息:从指定的队列中接收消息。
  • 消息转换:支持消息序列化和反序列化,可以将Java对象转换为消息或从消息中恢复Java对象。
java@Autowired  
private RabbitTemplate rabbitTemplate;  

// 发送消息  
// 1 交换机名称、2路由routing_key,3、发送的内容
rabbitTemplate.convertAndSend("exchangeName", "routingKey", "message");  

// 接收消息  
String message = (String) rabbitTemplate.receiveAndConvert("queueName");  


//发送一个延迟消息(30分钟)
MessagePostProcessor messagePostProcessor = message -> {
      message.getMessageProperties().setDelay(60*30 * 1000);//30分钟
      return message;
};
rabbitTemplate.convertAndSend("exchangeName", "routingKey", "message",messagePostProcessor);  



// 发送延迟消息(10秒)
@Test
public void testSendDelayMessage1() {
    rabbitTemplate.convertAndSend(
            EXCHANGE_DELAY,
            ROUTING_KEY_DELAY,
            "测试基于插件的延迟消息 [" + new SimpleDateFormat("hh:mm:ss").format(new Date()) + "]",
            messageProcessor -> {

              // 设置延迟时间:以毫秒为单位
              messageProcessor.getMessageProperties().setHeader("x-delay", "10000");
                 	

              return messageProcessor;
      });
}

RabbitService

RabbitService并不是Spring AMQP提供的标准组件,但它可能是一个自定义类,用于封装与RabbitMQ相关的业务逻辑。这个服务可能会使用RabbitTemplate进行实际的消息发送和接收操作,通过提供更高层次的API来简化与RabbitMQ的交互。

java@Service  
public class RabbitService {  
    
    @Autowired  
    private RabbitTemplate rabbitTemplate;  

    public void publishMessage(String exchange, String routingKey, String message) {  
        rabbitTemplate.convertAndSend(exchange, routingKey, message);  
    }  

    public String consumeMessage(String queueName) {  
        return (String) rabbitTemplate.receiveAndConvert(queueName);  
    }  
}  

2. MessageListener【处理信息】

MessageListener 接口用于定义如何处理接收到的消息。它通常与 SimpleMessageListenerContainerConcurrentMessageListenerContainer 一起使用。

java@Component  
public class MyMessageListener implements MessageListener {  
    @Override  
    public void onMessage(Message message) {  
        // 处理接收到的消息  
        String msgBody = new String(message.getBody());  
        System.out.println("Received message: " + msgBody);  
    }  
}  

3. RabbitMessageConverter【转换消息】

用于在发送和接收消息时进行消息的转换。常见的转换器包括 MappingJackson2MessageConverter(用于 JSON)和 SimpleMessageConverter(用于文本)。

java@Bean  
public RabbitMessagingTemplate rabbitMessagingTemplate(ConnectionFactory connectionFactory) {  
    RabbitMessagingTemplate template = new RabbitMessagingTemplate(connectionFactory);  
    template.setMessageConverter(new MappingJackson2MessageConverter());  
    return template;  
}  

4. RabbitAdmin【管理队列、交换机...】

RabbitAdmin 是一个自动化管理的组件,用于创建和删除队列、交换机和绑定关系等。

java@Autowired  
private RabbitAdmin rabbitAdmin;  

// 创建队列  
rabbitAdmin.declareQueue(new Queue("myQueue"));  

// 创建交换机  
rabbitAdmin.declareExchange(new DirectExchange("myExchange"));  

// 创建绑定  
rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("myQueue")).to(new DirectExchange("myExchange")).with("routingKey"));  

5. Queue, Exchange, Binding

在 Spring AMQP 中,队列、交换机和绑定是基本组件,分别用于消息存储、消息路由和连接队列与交换机。

//创建队列
@Bean  
public Queue myQueue() {  
    return new Queue("myQueue");  
}  
//创建交换机
@Bean  
public DirectExchange myExchange() {  
    return new DirectExchange("myExchange");  
}  
//交换机与队列进行绑定
@Bean  
public Binding myBinding() {  
    return BindingBuilder.bind(myQueue()).to(myExchange()).with("routingKey");  
} 

我们可以自己创建队列和交换机,不过SpringAMQP还提供了ExchangeBuilder来简化这个过程:

fanout示例

@Configuration
public class FanoutConfig {
    /**
     * 声明交换机
     * @return Fanout类型交换机
     */
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("hmall.fanout");
    }
    /**
     * 第1个队列
     */
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    /**
     * 第2个队列
     */
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

direct示例

@Configuration
public class DirectConfig {
    /**
     * 声明交换机
     * @return Direct类型交换机
     */
    @Bean
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange("hmall.direct").build();
    }
    /**
     * 第1个队列
     */
    @Bean
    public Queue directQueue1(){
        return new Queue("direct.queue1");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue1WithRed(Queue directQueue1, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue1).to(directExchange).with("red");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue1WithBlue(Queue directQueue1, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue1).to(directExchange).with("blue");
    }
    /**
     * 第2个队列
     */
    @Bean
    public Queue directQueue2(){
        return new Queue("direct.queue2");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue2WithRed(Queue directQueue2, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue2).to(directExchange).with("red");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue2WithYellow(Queue directQueue2, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue2).to(directExchange).with("yellow");
    }
}

基于注解声明创建队列和交换机

基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式来声明。基于@RabbitListener注解

Direct模式

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
    System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue2"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
    System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

Topic模式

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue1"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "china.#"
))
public void listenTopicQueue1(String msg){
    System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue2"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "#.news"
))
public void listenTopicQueue2(String msg){
    System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}

创建死信交换机和队列

@Configuration
public class DeadLetterMqConfig {
    // 声明一些变量

    public static final String exchange_dead = "exchange.dead";
    public static final String routing_dead_1 = "routing.dead.1";
    public static final String routing_dead_2 = "routing.dead.2";
    public static final String queue_dead_1 = "queue.dead.1";
    public static final String queue_dead_2 = "queue.dead.2";

    // 定义交换机
    @Bean
    public DirectExchange exchange() {
        return new DirectExchange(exchange_dead, true, false, null);
    }

    @Bean
    public Queue queue1() {
        // 设置如果队列一 出现问题,则通过参数转到exchange_dead,routing_dead_2 上!
        HashMap<String, Object> map = new HashMap<>();
        // 参数绑定 此处的key 固定值,不能随意写
        map.put("x-dead-letter-exchange", exchange_dead);
        map.put("x-dead-letter-routing-key", routing_dead_2);
        // 设置延迟时间
        map.put("x-message-ttl", 10 * 1000);
        // 队列名称,是否持久化,是否独享、排外的【true:只可以在本次连接中访问】,是否自动删除,队列的其他属性参数
        return new Queue(queue_dead_1, true, false, false, map);
    }

    @Bean
    public Binding binding() {
        // 将队列一 通过routing_dead_1 key 绑定到exchange_dead 交换机上
        return BindingBuilder.bind(queue1()).to(exchange()).with(routing_dead_1);
    }

    // 这个队列二就是一个普通队列
    @Bean
    public Queue queue2() {
        return new Queue(queue_dead_2, true, false, false, null);
    }

    // 设置队列二的绑定规则
    @Bean
    public Binding binding2() {
        // 将队列二通过routing_dead_2 key 绑定到exchange_dead交换机上!
        return BindingBuilder.bind(queue2()).to(exchange()).with(routing_dead_2);
    }
}

创建延迟队列

注意:需要安装延迟插件

https://github.com/rabbitmq/rabbitmq-delayed-message-exchange

@Configuration
public class CancelOrderMqConfig {
    
    @Bean
    public Queue cancelQueue() {
        // 第一个参数是创建的queue的名字,第二个参数是是否支持持久化
        return new Queue(queue_name, true);
    }
    //创建MQ的交换机
    @Bean
    public CustomExchange cancelExchange() {
        Map<String, Object> args = new HashMap<String, Object>();
        //设置配置参数
        args.put("x-delayed-type", "direct");
        //第一个参数是交换机名称、第二个参数是交换机类型
        //第三个参数是是否持久化、第四个参数是否自动删除
        //第五个参数是交换机的其他属性参数
        return new CustomExchange(exchange_name, "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding bindingCancel() {
        //创建的队列,去创建的交换机进行绑定。通过路由的routing_key,noargs() 表示该绑定不带任何额外的参数
        return BindingBuilder.bind(cancelQueue()).to(cancelExchange()).with(routing_key).noargs();
    }

}
posted @   CH_song  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示