spring-boot & spring 实现 rabbitMq rpc模式的消息发送与接收

简介:

      本篇文章是我个人最近学习rabbitMq的一次总结,通过实际框架中的项目配置和代码,来实现rpc风格的rabbitMq的使用,主要分为两个项目,分别实现发送,回复和接受回复的功能。

     本篇文章不是rabbitMq的入门篇,所有对于新入门的同学,对exchange,queue,routingKey这些概念还不懂的话,不建议看这篇文章。

主要分为两个项目:

1、spring框架的主要实现发送消息和接受回复消息的功能,以下简称生产者

2、spring boot框架的项目主要实现接受消息和回复消息的功能,以下简称消费者

 

废话不多说,直接上代码

1、生产者pom.xml片段,主要在原有框架中,添加spring-rabbit的依赖

		
			org.springframework.amqp
			spring-rabbit
			1.6.5.RELEASE
		

2、生产者配置文件,在resources下面新建rabbitMq.properties,内容如下

#rabbitMq
mq.ip=192.168.1.100
mq.port=5672
mq.userName=rabbitmq_producer
mq.password=123456
mq.virtualHost=test_vhosts

3、rabbit的spring配置文件,在resources下面新建spring-rabbitMq.xml,同时在web.xml中,像加载别的spring

配置文件一样配置一下。具体内容如下




    

    

    
    
        
        
        
        
        
    

    
    
        
    
    
    
        
        
    

    
    
        
        
        
        
        
        
        

    



    
    

    
    


    
    
        
        
        
        
        
        
        
        
    


    
    
        
        
        
        
        
        
        
    

    

    
    
        
        
        
        
        
    

    
    

    
  
        
        
        
        
        
        

   







    
    
        
        
        
        
        
        
    


    
    
        
        
        
        
        
        
    

    
    
        
        
        
        
        
    





需要注意的是,springReplyMessageQueue是专门用来回复的队列

4、SysRabbitProductTestController.java.  是写的一个用来测试发送消息并接收回复的测试类,这里面需要注意的是

 rabbitTemplate.sendAndReceive() 这个方法是默认等待5秒钟,如果在5秒内没有接收到回复的话,会返回一个空的message,这个默认的时间,实在spring-rabbit.xml中的rabbittemplete的配置的replyTimeout 来设置.

另外:使用sendAndReceive 这个方法发送消息时,消息的correlationId会变成系统动编制的1,2,3这个样子,而不是我们想要的

uuid的格式。

 

 


import com.rabbitmq.client.AMQP;
import com.sime.controller.base.BaseController;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.MessagePropertiesConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.UUID;


/*
*
 *  rabbitMq 发送测试
*/


@Controller
@RequestMapping("rabbitTest/")
public class SysRabbitProductTestController extends BaseController {

    @Autowired
    private MessagePropertiesConverter messagePropertiesConverter;


    @Autowired
    private RabbitTemplate rabbitTemplate;


    @RequestMapping("send")
    @ResponseBody
    public  String send(){
        String correlationId = UUID.randomUUID().toString();
        Date sendTime = new Date();
        AMQP.BasicProperties props =
                new AMQP.BasicProperties("text/plain",
                        "UTF-8",
                        null,
                        2,
                        0, correlationId, "springReplyMessageExchange", null,
                        null, sendTime, null, null,
                        "SpringProducer", null);


        MessageProperties sendMessageProperties =
                messagePropertiesConverter.toMessageProperties(props, null,"UTF-8");
         sendMessageProperties.setReceivedExchange("springReplyMessageExchange");
        sendMessageProperties.setReceivedRoutingKey("springReplyMessage");
        sendMessageProperties.setRedelivered(true);
         String message = "fa song xiaoxi ------------ 走你"; 
     

        try {
         //发送并接收回执
        Message sendMessage = MessageBuilder.withBody(message.getBytes("UTF-8"))
                     .andProperties(sendMessageProperties)
                    .build();


        Message replyMessage =   rabbitTemplate.sendAndReceive("springMessageExchange",
                        "springMessage", sendMessage);

        String replyMessageContent = null;
        replyMessageContent = new String(replyMessage.getBody(),"UTF-8");
        System.out.println("接收到回执:  "+replyMessageContent);
        return replyMessageContent;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

}

 

6、下面是消费者的pom.xml 的重要片段

       
            org.springframework.boot
            spring-boot-starter-amqp
        

        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

 

7、application.yml 关于rabbitMq的配置

spring:  
    rabbitmq:
      username: rabbitmq_consumer
      host: 192.168.1.100
      port: 5672
      password: 123456
      virtual-host: test_vhosts

8、常量配置类AppConstants

public class AppConstants {
    public static final String SEND_QUEUE_NAME = "springMessageQueue";
    public static final String SEND_EXCHANGE_NAME = "springMessageExchange";
    public static final String SEND_MESSAGE_KEY = "springMessage"; 
 

}

 

 

9、配置类 RabbitConfig.java

 
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.sime.constants.AppConstants;

import com.sime.rabbit.FinancMessageListener;
import com.sime.service.UserService;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpoint;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter;
import org.springframework.amqp.rabbit.support.MessagePropertiesConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(RabbitProperties.class)
public class RabbitConfig {
    @Autowired
    private RabbitProperties rabbitProperties;


    @Bean("connectionFactory")
    public ConnectionFactory getConnectionFactory() {
        com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory =
                new com.rabbitmq.client.ConnectionFactory();
        rabbitConnectionFactory.setHost(rabbitProperties.getHost());
        rabbitConnectionFactory.setPort(rabbitProperties.getPort());
        rabbitConnectionFactory.setUsername(rabbitProperties.getUsername());
        rabbitConnectionFactory.setPassword(rabbitProperties.getPassword());
        rabbitConnectionFactory.setVirtualHost(rabbitProperties.getVirtualHost());

        ConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitConnectionFactory);
        return connectionFactory;

    }

    @Bean(name="rabbitAdmin")
    public RabbitAdmin getRabbitAdmin() {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(getConnectionFactory());
        rabbitAdmin.setAutoStartup(true);
        return rabbitAdmin;

    }



    @Bean(name="serializerMessageConverter")
    public MessageConverter getMessageConverter(){
        return new SimpleMessageConverter();
    }

    @Bean(name="messagePropertiesConverter")
    public MessagePropertiesConverter getMessagePropertiesConverter()
    {
        return new DefaultMessagePropertiesConverter();
    }




    @Bean(name="rabbitTemplate")
    public RabbitTemplate getRabbitTemplate()
    {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
        rabbitTemplate.setUseTemporaryReplyQueues(false);
        rabbitTemplate.setMessageConverter(getMessageConverter());
        rabbitTemplate.setMessagePropertiesConverter(getMessagePropertiesConverter());
    
        return rabbitTemplate;
    }

  

    @Bean(name="springMessageQueue")
    public Queue createQueue(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
         Queue sendQueue = new  Queue(AppConstants.SEND_QUEUE_NAME,true,false,false);
        rabbitAdmin.declareQueue(sendQueue);
        return sendQueue;
    }

    @Bean(name="springMessageExchange")
    public Exchange createExchange(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        DirectExchange sendExchange = new DirectExchange(AppConstants.SEND_EXCHANGE_NAME,true,false);
        rabbitAdmin.declareExchange(sendExchange);
        return sendExchange;
    }

    @Bean(name="springMessageBinding")
    public Binding createMessageBinding(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        Map arguments = new HashMap();
        Binding sendMessageBinding =
                new Binding(AppConstants.SEND_QUEUE_NAME, Binding.DestinationType.QUEUE,
                        AppConstants.SEND_EXCHANGE_NAME, AppConstants.SEND_MESSAGE_KEY, arguments);
        rabbitAdmin.declareBinding(sendMessageBinding);
        return sendMessageBinding;
    }


}
 

 

10.消息接收Listener类


public class FinancMessageListener implements ChannelAwareMessageListener  {

    @Autowired
    private MessagePropertiesConverter messagePropertiesConverter;

  @Autowired
  private UserService userService;

  @Autowired
  private RabbitTemplate rabbitTemplate;

  @Override
  public void onMessage(Message message, Channel channel) throws Exception {
    System.out.println("+++++++++++++++++++++++++++++接收到消息了+++++++++++++++++++++++++++"+userService);
    System.out.println(new String(message.getBody(),"UTF-8"));
      try
      {

          MessageProperties messageProperties = message.getMessageProperties();
          AMQP.BasicProperties rabbitMQProperties =
                  messagePropertiesConverter.fromMessageProperties(messageProperties, "UTF-8");
          String messageContent = null;
          messageContent = new String(message.getBody(),"UTF-8");
          String consumerTag = messageProperties.getConsumerTag();
          System.out.println(consumerTag+ " get The message content is:" + messageContent);


          /**************************返回消息,5秒以内返回*************************************************/
            //RPC回复 ,发送消息
            String replyMessageContent = "Consumer1 返回的信息 '" + messageContent +" consumerTag:  "+consumerTag+ "'";


            String cId = rabbitMQProperties.getCorrelationId();
          AMQP.BasicProperties replyRabbitMQProps =
              new AMQP.BasicProperties("text/plain",
                      "UTF-8",
                      null,
                      2,
                      0, cId, null, null,
                      null, null, null, null,
                      consumerTag, null);
          Envelope replyEnvelope =
                  new Envelope(messageProperties.getDeliveryTag(), true,
                          "springReplyMessageExchange", "springReplyMessage");

          MessageProperties replyMessageProperties =
                  messagePropertiesConverter.toMessageProperties(replyRabbitMQProps,
                          replyEnvelope,"UTF-8");

          Message replyMessage = MessageBuilder.withBody(replyMessageContent.getBytes("UTF-8"))
                  .andProperties(replyMessageProperties)
                  .build();


          rabbitTemplate.send("springReplyMessageExchange","springReplyMessage", replyMessage);
          channel.basicAck(messageProperties.getDeliveryTag(), false);



      }
      catch (Exception e) {
            e.printStackTrace();
      }


  }
 }

 

 

截止到此,关键的部分的代码就完成了,仅做记录

参考:https://blog.csdn.net/u011126891/article/details/54376179

 

 

 

 

 

你可能感兴趣的:(学习笔记,rabbitMq,rpc,spring,boot)