SpringBoot - 整合RabbitMQ

【1】添加starter导入组件

pom文件如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--<dependency>-->
    <!--<groupId>javax.cache</groupId>-->
    <!--<artifactId>cache-api</artifactId>-->
<!--</dependency>-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

【2】RabbitMQ属性配置

application.properties中配置如下:

spring.rabbitmq.host=192.168.2.110
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
# 下面两个是默认值,可以不用显示指定
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/

【3】测试发送接收消息

引入rabbitmq相关的starter后,RabbitAutoConfiguration就会默认对RabbitMQ进行配置。

主要配置如下:

  • 自动配置了连接工厂ConnectionFactory;
  • RabbitProperties封装了RabbitMQ的属性配置;
  • RabbitTemplate用来发送接收消息;
  • AmqpAdmin–RabbitMQ系统管理功能组件。

这里使用RabbitTemplate测试消息发送和接收,源码如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootRabbitMQTests {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    public void testSend(){
        Map<String,Object> map = new HashMap<>();
        map.put("msg","第一条消息");
        map.put("data", Arrays.asList("hello",true,"中"));
        rabbitTemplate.convertAndSend("exchange.direct","rabbitmq",map);
    }

    @Test
    public void testReceive(){
        Object o = rabbitTemplate.receiveAndConvert("rabbitmq");
        System.out.println(o.getClass());
        System.out.println(o);
    }
}

发送后查看后台队列并获取消息如下图:

这里写图片描述


接收如下图所示:

这里写图片描述


【4】替换默认的MessageConverter

如下图所示,RabbitTemplate默认使用的是SimpleMessageConverter:

这里写图片描述

该转换器默认使用SerializationUtils进行序列化和反序列化。

这里如果想将数据序列化为JSON格式,方便查看,可以注册自定义的转换器(ampq包下的转换器)。

源码示例如下:

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by Janus on 2018/7/6.
 */
@Configuration
public class MyAMQPConfig {

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

再次发送消息后台管理页面查看队列:

这里写图片描述

其他交换器类型的发送和接收,与上面相同,只是改一下对应交换器的名字即可。


【5】基于注解的RabbitMQ

① @EnableRabbit注解开启基于注解的RabbitMQ

@SpringBootApplication
@EnableCaching
@EnableRabbit
public class SpringBoot01CacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot01CacheApplication.class, args);
    }
}

② @RabbitListener

源码如下:

/**
 * Annotation that marks a method to be the target of a Rabbit message
 * listener on the specified {@link #queues()} (or {@link #bindings()}).
 * The {@link #containerFactory()}
 * identifies the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory
 * RabbitListenerContainerFactory} to use to build the rabbit listener container. If not
 * set, a <em>default</em> container factory is assumed to be available with a bean
 * name of {@code rabbitListenerContainerFactory} unless an explicit default has been
 * provided through configuration.
 *
 * <p>Processing of {@code @RabbitListener} annotations is performed by
 * registering a {@link RabbitListenerAnnotationBeanPostProcessor}. This can be
 * done manually or, more conveniently, through the {@code <rabbit:annotation-driven/>}
 * element or {@link EnableRabbit} annotation.
 *
 * <p>Annotated methods are allowed to have flexible signatures similar to what
 * {@link MessageMapping} provides, that is
 * <ul>
 * <li>{@link com.rabbitmq.client.Channel} to get access to the Channel</li>
 * <li>{@link org.springframework.amqp.core.Message} or one if subclass to get
 * access to the raw AMQP message</li>
 * <li>{@link org.springframework.messaging.Message} to use the messaging abstraction counterpart</li>
 * <li>{@link org.springframework.messaging.handler.annotation.Payload @Payload}-annotated method
 * arguments including the support of validation</li>
 * <li>{@link org.springframework.messaging.handler.annotation.Header @Header}-annotated method
 * arguments to extract a specific header value, including standard AMQP headers defined by
 * {@link org.springframework.amqp.support.AmqpHeaders AmqpHeaders}</li>
 * <li>{@link org.springframework.messaging.handler.annotation.Headers @Headers}-annotated
 * argument that must also be assignable to {@link java.util.Map} for getting access to all
 * headers.</li>
 * <li>{@link org.springframework.messaging.MessageHeaders MessageHeaders} arguments for
 * getting access to all headers.</li>
 * <li>{@link org.springframework.messaging.support.MessageHeaderAccessor MessageHeaderAccessor}
 * or {@link org.springframework.amqp.support.AmqpMessageHeaderAccessor AmqpMessageHeaderAccessor}
 * for convenient access to all method arguments.</li>
 * </ul>
 *
 * <p>Annotated methods may have a non {@code void} return type. When they do, the result of the
 * method invocation is sent as a reply to the queue defined by the
 * {@link org.springframework.amqp.core.MessageProperties#getReplyTo() ReplyTo}  header of the
 * incoming message. When this value is not set, a default queue can be provided by
 * adding @{@link org.springframework.messaging.handler.annotation.SendTo SendTo} to the method
 * declaration.
 *
 * <p>When {@link #bindings()} are provided, and the application context contains a
 * {@link org.springframework.amqp.rabbit.core.RabbitAdmin},
 * the queue, exchange and binding will be automatically declared.
 *
 * <p>When defined at the method level, a listener container is created for each method. The
 * {@link MessageListener} is a {@link MessagingMessageListenerAdapter}, configured with a
 * {@link org.springframework.amqp.rabbit.listener.MethodRabbitListenerEndpoint}.
 *
 * <p>When defined at the class level, a single message listener container is used to service
 * all methods annotated with {@code @RabbitHandler}. Method signatures of such annotated
 * methods must not cause any ambiguity such that a single method can be resolved for a
 * particular inbound message. The {@link MessagingMessageListenerAdapter} is configured with
 * a {@link org.springframework.amqp.rabbit.listener.MultiMethodRabbitListenerEndpoint}.
 *
 * @author Stephane Nicoll
 * @author Gary Russell
 * @since 1.4
 * @see EnableRabbit
 * @see RabbitListenerAnnotationBeanPostProcessor
 * @see RabbitListeners
 */
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@MessageMapping
@Documented
@Repeatable(RabbitListeners.class)
public @interface RabbitListener {
    String id() default "";

    String containerFactory() default "";

    String[] queues() default {};

    boolean exclusive() default false;

    String priority() default "";

    String admin() default "";

    QueueBinding[] bindings() default {};

    String group() default "";
}

测试实例如下:

@Service
public class RabbitListenerService {

    @RabbitListener(queues = {"rabbitmq"})
    public void receive(Map<String,Object> map){

        System.out.println("从队列rabbitmq获取到数据 : "+map);
    }
}

启动项目,一旦rabbitmq队列中有消息, 即会获取并打印,测试结果如下:

这里写图片描述


③ 获取消息头信息

不光可以直接获取消息体信息,还可以使用Message作为参数,从中分别获取消息体和消息头,源码示例如下:

 @RabbitListener(queues = {"rabbitmq.news"})
 public void receiveMessage(Message message){
      System.out.println("从消息中获取的消息体:"+message.getBody());
      System.out.println("从消息中获取的消息头信息 : "+message.getMessageProperties());
  }

测试结果如下图:

这里写图片描述


【6】AmqpAdmin编码创建交换器、队列并进行绑定

上面测试是提前创建好了交换器、队列并将其进行了绑定,实际项目中时常会遇到需要编码创建上述组件。这时,就可以使用AmqpAdmin进行操作。

源码示例如下:

    @Autowired
    AmqpAdmin amqpAdmin;

    @Test
    public void createByAmqpAdmin(){
        //创建交换器
        amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));
        System.out.println("创建交换器完成");
        //创建队列
        amqpAdmin.declareQueue(new Queue("amqpadmin.queue",true));
        Binding binding = new Binding("amqpadmin.queue", Binding.DestinationType.QUEUE,"amqpadmin.exchange","amqpadmin",null);
        amqpAdmin.declareBinding(binding);
    }

测试结果如下:

这里写图片描述
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/j080624/article/details/80944765