Abstract:

In this article, we will integrate the message middleware RabbitMQ, including adding dependencies, adding configuration information, and customizing the operation components such as RabbitTemplate to send and receive messages. And in the next chapter, it will be integrated with mail service to realize the function of “users successfully send email notification messages in seconds”!

Content:

For the RabbitMQ message middleware, every friend have not used, must also have heard of this, it is a fairly widely applied on market at present is message oriented middleware, can realize decoupling news asynchronous communication, business service module, interface, current limiting, news distribution, and other functions, in service, the distributed system architecture is plays a great role! (Detailed introduction, Debug is not described here, you can go to the official website to see more introduction and typical application scenarios)!

In this post we will use RabbitMQ as a message delivery component, combining it with the mail service described in the following sections to send mail notifications asynchronously to the user to inform them of their success. “, let’s go into the actual code.

(1) To use RabbitMQ, install the RabbitMQ service in the local development environment or server. As shown in the following figure, Debug accesses the home page of the back-end console application after the RabbitMQ service is installed successfully:



Then we started integrating it with SpringBoot. The dependencies need to be added first, and the version number is the same as SpringBoot’s 1.5.7.release:

<! --rabbitmq--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId>  <version>${spring-boot.version}</version>
</dependency>
Copy the code

Then add the RabbitMQ service configuration to the application.properties file, such as Host, Port, and so on:

#rabbitmqSpring. The rabbitmq. Virtual - host = / spring. The rabbitmq. Host = 127.0.0.1 spring. The rabbitmq. Port = 5672 spring. The rabbitmq. Username = guest spring.rabbitmq.password=guest spring.rabbitmq.listener.simple.concurrency=5 spring.rabbitmq.listener.simple.max-concurrency=15 spring.rabbitmq.listener.simple.prefetch=10Copy the code

(2) Next, with SpringBoot’s natural features, we automatically inject the configuration of RabbitMQ components, including its single instance consumer configuration, multi-instance consumer configuration, and the operation component instance for sending messages, RabbitTemplate:

@configuration public class RabbitmqConfig {private final static Loggerlog= LoggerFactory.getLogger(RabbitmqConfig.class); @Autowired private Environment env; @Autowired private CachingConnectionFactory connectionFactory; @Autowired private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer; // Single consumer @bean (name ="singleListenerContainer")
  public SimpleRabbitListenerContainerFactory listenerContainer(){
      SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
      factory.setConnectionFactory(connectionFactory);
      factory.setMessageConverter(new Jackson2JsonMessageConverter());
      factory.setConcurrentConsumers(1);
      factory.setMaxConcurrentConsumers(1);
      factory.setPrefetchCount(1);
      factory.setTxSize(1);
      returnfactory; } // Multiple consumers @bean (name ="multiListenerContainer")
  public SimpleRabbitListenerContainerFactory multiListenerContainer(){ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factoryConfigurer.configure(factory,connectionFactory); factory.setMessageConverter(new Jackson2JsonMessageConverter()); / / confirm the consumption mode - NONE factory. SetAcknowledgeMode (AcknowledgeMode. NONE); factory.setConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.concurrency",int.class));
      factory.setMaxConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.max-concurrency",int.class));
      factory.setPrefetchCount(env.getProperty("spring.rabbitmq.listener.simple.prefetch",int.class));
      return factory;
  }

  @Bean
  public RabbitTemplate rabbitTemplate(){
      connectionFactory.setPublisherConfirms(true);
      connectionFactory.setPublisherReturns(true);
      RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
      rabbitTemplate.setMandatory(true);
      rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
          @Override
          public void confirm(CorrelationData correlationData, boolean ack, String cause) {
              log.info("Message sent successfully :correlationData({}), ACK ({}),cause({})",correlationData,ack,cause); }}); rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
          @Override
          public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
              log.warn("Message loss: exchange ({}), the route ({}), replyCode ({}), replyText ({}), message: {}",exchange,routingKey,replyCode,replyText,message); }});returnrabbitTemplate; }}Copy the code

The RabbitMQ message sending component RabbitTemplate is configured with “message sending confirmation” and “message loss callback”, that is, when the message is correctly queued, it means that the message is successfully sent. The output message is lost when the message cannot find the corresponding queue (and to some extent, the switch and route).

(3) With that done, we are ready to use RabbitMQ to send and receive messages. First, we need to create the queue, switch, route and binding Bean components in the RabbitmqConfig configuration class, as follows:

// Build a message model @bean public Queue that asynchronously sends mailbox notificationssuccessEmailQueue() {return new Queue(env.getProperty("mq.kill.item.success.email.queue"),true);
    }

    @Bean
    public TopicExchange successEmailExchange() {return new TopicExchange(env.getProperty("mq.kill.item.success.email.exchange"),true.false);
    }

    @Bean
    public Binding successEmailBinding() {return BindingBuilder.bind(successEmailQueue()).to(successEmailExchange()).with(env.getProperty("mq.kill.item.success.email.routing.key"));
    }
Copy the code

Where the environment variable instance env reads properties that we configure in the application.properties file, as shown below:

mq.env=test

A message model that successfully sends messages asynchronously
mq.kill.item.success.email.queue=${mq.env}.kill.item.success.email.queue
mq.kill.item.success.email.exchange=${mq.env}.kill.item.success.email.exchange
mq.kill.item.success.email.routing.key=${mq.env}.kill.item.success.email.routing.key
Copy the code

Next, we need to write a method to send a message to RabbitSenderService, the generic message sending service, which receives the order number parameter, queries the database for its detailed order record, and sends it as a message to the RabbitMQ queue. Consumption waiting to be monitored:

* @author :debug (SteadyJack) * @date: 2019/6/21 21:47 **/ @Service public class RabbitSenderService { public static final Loggerlog= LoggerFactory.getLogger(RabbitSenderService.class); @Autowired private RabbitTemplate rabbitTemplate; @Autowired private Environment env; @Autowired private ItemKillSuccessMapper itemKillSuccessMapper; Public void sendKillSuccessEmailMsg(String orderNo){log.info()"Seckill success send email notification message asynchronously - ready to send message: {}",orderNo);

      try {
          if (StringUtils.isNotBlank(orderNo)){
              KillSuccessUserInfo info=itemKillSuccessMapper.selectByCode(orderNo);
              if(info! = null) {/ / TODO: the logic of the rabbitmq sending messages rabbitTemplate. SetMessageConverter (new Jackson2JsonMessageConverter ()); rabbitTemplate.setExchange(env.getProperty("mq.kill.item.success.email.exchange"));
                  rabbitTemplate.setRoutingKey(env.getProperty("mq.kill.item.success.email.routing.key")); / / TODO: will the info ACTS as a message is sent to the queue rabbitTemplate. ConvertAndSend (info, newMessagePostProcessor() {
                      @Override
                      public Message postProcessMessage(Message message) throws AmqpException {
                          MessageProperties messageProperties=message.getMessageProperties();
                          messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                          messageProperties.setHeader(AbstractJavaTypeMapper.DEFAULT_CONTENT_CLASSID_FIELD_NAME,KillSuccessUserInfo.class);
                          returnmessage; }}); } } }catch (Exception e){ log.error("Seckill success send email notification message asynchronously - exception occurred, message: {}",orderNo,e.fillInStackTrace()); }}}Copy the code

RabbitReceiverService RabbitReceiverService RabbitReceiverService RabbitReceiverService RabbitReceiverService

* @author :debug (SteadyJack) * @date: 2019/6/21 21:47 **/ @Service public class RabbitReceiverService { public static final Loggerlog= LoggerFactory.getLogger(RabbitReceiverService.class); @Autowired private MailService mailService; @Autowired private Environment env; @Autowired private ItemKillSuccessMapper itemKillSuccessMapper; // Queues = {RabbitListener(queues = {"${mq.kill.item.success.email.queue}"},containerFactory = "singleListenerContainer")
  public void consumeEmailMsg(KillSuccessUserInfo info){
      try {
          log.info("Seckill asynchronous mail notification - Receive message :{}",info); }catch (Exception e){log.error()"Seckill asynchronous email notification - Receive message - Exception occurs:",e.fillInStackTrace()); }}}Copy the code

This article concludes the code for SpringBoot’s RabbitMQ integration middleware.

The last thing we need to test is that RabbitMQ will send and receive a message from the user when a snap request is made:



Well, that’s the end of this article and in the next article we’ll integrate RabbitMQ with the mail service to send notification messages asynchronously to the user’s mailbox after a successful kill. In addition, we will explain how to use RabbitMQ’s dead-letter queue to process an order that has expired after the user placed it, where we will invalidate it.

Supplement:

1, at present, the overall construction of the second kill system and code combat has been completed, the complete source code database address can be downloaded here: gitee.com/steadyjack/… Remember Fork and Star!!

2. Finally, don’t forget to pay attention to Debug’s wechat official account: