SpringBoot 中文手册 --Part IV --32 消息

本文翻译自 Spring Boot 官方文档 -32.Messaging

32. 消息

Spring 框架对整合消息系统提供了大量的支持:从简单的JMS API使用到使用 JmsTemplate 来完成接受异步消息的基础框架。Spring AMQP 为‘Advanced Message Queuing Protocol’提供了相同的特性集,Spring Boot也为RabbitTemplate 和RabbitMQ提供了自动配置项。我们在Spring WebSocket中支持原生的STOMP消息,而且Spring Boot通过Starters和少量的自动配置为其提供支持。Spring Boot也支持Apache Kafka。

32.1 JMS

javax.jms.ConnectionFactory接口提供了创建javax.jms.Connection标准方法来和JMS broker互相通讯。尽管Spring需要一个 ConnectionFactory来和JMS协作,但是通常你不需要直接使用它,完全可通过上层的消息封装代替操作(详见Spring框架参考手册的相关章节)。Spring Boot给发送和接受消息的必要基础组件提供了自动配置。

32.1.1 ActiveMQ 支持

Spring Boot会在类路径上发现ActiveMQ可用时配置一个ConnectionFactory。如果存在中间件,一个内部的中间件会自动启动并被配置(只要配置中没有指定中间件URL)。

| 如果你在使用 spring-boot-starter-activemq,连接所必需的依赖或内嵌的ActiveMQ实例会被提供,以及与JMS整合的Spring基础结构。

ActiveMQ配置由外部的在spring.activemq.*中的配置属性控制。例如,你可在application.properties中声明下面的部分:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin 
spring.activemq.password=secret 

你可以通过给org.apache.activemq:activemq-pool增加依赖并配置PooledConnectionFactory 因此:

spring.activemq.pool.enable=true
spring.activemq.pool.max-connections=50

| 查看 ActiveMQProperties 获取更多支持选项。你也可注册任意数量的实现ActiveMQConnectionFactoryCustomizer的beans获得更多高级定制。

默认ActiveMQ会在队列不存在时创建一个,以便根据他们提供的名字来转变。

32.1.2 Artemis 支持

Spring Boot会在类路径上发现Artemis时自动配置一个ConnectionFactory。如果broker存在,一个内部的broker会自动启动和配置(除非这模型属性被明确设置)。支持的模型有:embedded(要明确请求的是内部broker并在类路径上没有可用的broker时引导到一个错误上),和native 使用netty传输协议连接到一个broker。当配置后者时,Spring Boot配置一个ConnectionFactory连接到一个使用默认设置运行在本地机器上的broker。

| 如果你正在使用spring-boot-starter-artemis连接到一个存在的Artemis实例的必须依赖将被提供,此外Spring会和JMS整合为基础架构。给你的应用增加org.apache.activemq:artemis-jms-server允许你使用内部的模型。

Artemis 配置由spring.artemis.*中的外部配置属性控制。例如,你可能在application.properties声明了以下部分:

spring.artemis.mode=native
spring.artemis.host=192.168.1.210
spring.artemis.port=9876
spring.artemis.user=admin
spring.artemis.password=secret

因为内置了broker,你可以选择是否开启持久态和可用终点列表。使用逗号分隔的列表会使用默认选项创建,或者你可以定义类型为org.apache.activemq.artemis.jms.server.config.JMSQueueConfigurationorg.apache.activemq.artemis.jms.server.config.TopicConfiguration的bean(s) 分别用于高级队列和主题配置。

查看ArtemisProperties 获得更多支持的操作。

JNDI查找没有参与这些工作,destinations根据他们自己的名字来解决,即可使用Artemis配置中的‘name’属性,也可通过配置提供名称。

32.1.3 使用JNDI 连接工厂

如果你在应用服务器上运行你的应用,Spring Boot会尝试使用JNDI定位一个JMS的ConnectionFactory。默认检查Java:/JmsXAjava:/XAConnectionFactory位置。如果需要制定其他位置,你可以使用spring.jms.jndi-name属性:

  spring.jms.jndi-name=java:/MyConnectionFactory

32.1.4 发送消息

Spring的JMSTemplate是自动配置的,你可以在你的beans中直接自动装配。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final JmsTemplate jmsTemplate;

    @Autowired
    public MyBean(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    // ...

}

| JmsMessageTemplate 可使用类似的方式注入。如果DestinationResolverMessageConverterbeans被定义,他们将根据自动配置的JmsTemlate自动适应。

32.1.5 接受消息

当JMS基础组件存在时,任何bean可使用@JmsListenter注解来创建一个监听端点。如果没有JMSListenerConnectionFactory被定义,默认的那个会自动配置。如果 DestinationResolverMessageConverter beans 被定义,他们会根据默认的工厂自动适应。

通常,默认的工厂是事务性的。如果你在一个存在JtaTransactionManager的基础框架上,它将关联默认的监听容器。如果不存在,sessionTransacted标识位将可用。对于后者,你可以在你的监听方法(或委派它的代表)上增加@Transactional来将你本地的数据存储事务交给进来的消息处理。请确保进来的消息在本地事务完成时知晓。这还包括在同一JMS回话上执行响应的消息。

下面的组件在someQueue目的节点创建一个监听:

@Component
public class MyBean {

    @JmsListener(destination = "someQueue")
    public void processMessage(String content) {
        // ...
    }

}

| 查看 @EnableJms的javadoc获得更多细节

如果你想创建更多的 JmsListenerContainerFactory实例或者你想重写默认的,Spring Boot提供DefaultJmsListenerContainerFactoryConfigurer让你用来初始化一个和自动配置相同设置的DefaultJmsListenerContainerFactory

例如,下面的例子期望另一个工厂使用指定的MessageConverter

@Configuration
static class JmsConfiguration {

    @Bean
    public DefaultJmsListenerContainerFactory myFactory(
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory());
        factory.setMessageConverter(myMessageConverter());
        return factory;
    }

}

然后你可以像下面一样使用任何@JmsListener注解的方法:

@Component
public class MyBean {

    @JmsListener(destination = "someQueue", containerFactory="myFactory")
    public void processMessage(String content) {
        // ...
    }

}

32.2 AMQP

高级消息队列协议(AMQP)是一个中立平台,为面向消息的中间件线级协议。Spring AMQP工程是应用Spring核心概念来开发基于AMQP的消息解决方案。Spring Boot通过RabbitMQ为和AMQP工作提供了一些便利,这些包含在spring-boot-starter-amqp起步器中。

32.2.1 RabbitMQ支持

RabbitMQ是一个轻量,可靠,可拓展和易用的基于AMQP协议的消息中间件。Spring使用RabbitMQ来使用AMQP协议通讯。

RabbitMQ配置被在外部spring.rabbitmq.*中的配置属性控制。例如,你可能在application.properties中声明了下面的部分:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret

查看RabbitProperties 获得更多支持操作。

| 查阅 Understanding AMQP, the protocol used by RabbitMQ 获得更多详情。

32.2.2 发送消息

Spring的AmqpTemplateAmqpAdmin被自动配置,你可直接在你的beans中自动装配他们:

import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final AmqpAdmin amqpAdmin;
    private final AmqpTemplate amqpTemplate;

    @Autowired
    public MyBean(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {
        this.amqpAdmin = amqpAdmin;
        this.amqpTemplate = amqpTemplate;
    }

    // ...

}

| RabbitMessagingTemplate 可以同样的方式注入。如果定义了MessageConverter,它会自动适应自动配置的AmqpTemplate

任何org.springframework.amqp.core.Queue被定义为一个bean都将自动用于在RabbitMQ实例上必要时声明适当的队列。

你可以开启AmqpTemplate的重试来重复操作,例如在中间件连接丢失事件上的重连。默认重试是禁用的。

32.2.3 接收消息

在Rabbit组件存在时,任何bean都可以使用@RabbitListener注解来创建一个监听节点。如果没有RabbitListenerContainerFactory被定义,默认的bean会被自动配置。如果MessageConverterMessageRecovererbeans被定义,他们会自动适应默认的工厂。

下面的组件,在someQueue队列上创建一个监听终端:

@Component
public class MyBean {

    @RabbitListener(queues = "someQueue")
    public void processMessage(String content) {
        // ...
    }

}

| 查阅 @EnableRabbit的Java手册 获得更多细节。

如果你需要创建更多的’RabbitListenerContainerFactory’实例或你想重写默认的,Spring Boot 提供一个SimpleRabbitListenerContainerFactoryConfigurer以便你可以用来初始化一个和自动配置相同设置的SimpleRabbitListenerContainerFactory

例如,下面展示了使用特定MessageConverter的另一个工厂;

@Configuration
static class RabbitConfiguration {

    @Bean
    public SimpleRabbitListenerContainerFactory myFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer) {
        SimpleRabbitListenerContainerFactory factory =
                new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setMessageConverter(myMessageConverter());
        return factory;
    }

}

然后想下面一样用在任何@RabbitListener注解的方法上:

@Component
public class MyBean {

    @RabbitListener(queues = "someQueue", containerFactory="myFactory")
    public void processMessage(String content) {
        // ...
    }

}

你可以开启重试来处理你的监听器在哪里抛出异常的情况。默认使用的RejectAndDontRequeueRecoverer除非定义了你自己的MessageRecoverer。当重试次数用尽,消息将被拒绝,或删除,或发送给私信交换在Broker这样配置时。重试默认是禁用的。

| Important
如果重试次数未开启,监听器抛出了异常,通常传递会无限次的重试。你可以用两种方式修改此行为;设置defaultRequeueRejected属性为false将尝试零重交付;或抛出一个 AmqpRejectAndDontRequeueException给拒绝消息的信号。这些是用在重试开启并在达到最大尝试次数时的使用技巧。

32.3 Apache Kafka 支持

Apache Kafka 的支持是通过提供spring-kafka工程的自动配置实现的。

Kafka配置由spring.kafka.*中的配置属性控制。例如,你在application.properties中配置了下面的部分:

spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup

查看KafkaProperties获得更多支持操作。

32.3.1 发送消息

Spring的KafkaTemplate是自动配置的,你可以直接自动装配他们到你的beans中:

@Component
public class MyBean {

    private final KafkaTemplate kafkaTemplate;

    @Autowired
    public MyBean(KafkaTemplate kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    // ...

}

32.3.2 接收消息

Apache Kafka组件存在时,任何bean可以使用@KafkaListener注解来创建一个监听终端。如果KafkaListenerContainerFactory没被定义,默认的工厂会使用定义在spring.kafka.listener.*中的键自动配置。

下面组件在someTopic规则上创建一个监听终端:

@Component
public class MyBean {

    @KafkaListener(topics = "someTopic")
    public void processMessage(String content) {
        // ...
    }

}

32.3.3 另外的Kafka 属性

自动配置支持的属性显示在 [Appendix A, Common application properties](Appendix A, Common application properties).注意这些属性(连字符连接的 或驼峰式)大部分直接对应到Apache Kafka点分隔的属性。详细对照Apache Kafka文档。

这些属性中的前几个应用于生产者和消费者,但如果你希望分别为他们使用不同的值,则可以在生产者或消费者基表指定。Apache Kafka指定属性附带价值:高、中和低。Spring Boot自动配置支持所有的高级,少数可选的中级和低级 和任何没有默认值的属性。

仅一些Kafka支持的属性子集可通过KafkaProperties类获得。如果你希望给生产者或消费者配置额外不直接支持的属性,使用下述属性:

spring.kafka.properties.foo.bar=baz

该设置设置公共foo.barKafka属性为baz

这些属性将被生产者和消费者工厂beans共享。如果你希望定制这些组件使用不同的属性,只需为每一个使用不同的度量读入器,你可以像下面一样重写这个bean的定义:

@Configuration
public static class CustomKafkaBeans {

    /**
     * Customized ProducerFactory bean.
     * @param properties the kafka properties.
     * @return the bean.
     */
    @Bean
    public ProducerFactory kafkaProducerFactory(KafkaProperties properties) {
        Map producerProperties = properties.buildProducerProperties();
        producerProperties.put(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
                MyProducerMetricsReporter.class);
        return new DefaultKafkaProducerFactory(producerProperties);
    }

    /**
     * Customized ConsumerFactory bean.
     * @param properties the kafka properties.
     * @return the bean.
     */
    @Bean
    public ConsumerFactory kafkaConsumerFactory(KafkaProperties properties) {
        Map consumerProperties = properties.buildConsumerProperties();
        consumerProperties.put(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
                MyConsumerMetricsReporter.class);
        return new DefaultKafkaConsumerFactory(consumerProperties);
    }

}

你可能感兴趣的:(SpringBoot,spring,框架,SpringBoot,消息)