Maison  >  Article  >  Java  >  Aperçu rapide de la façon dont Spring Boot prend en charge JMS

Aperçu rapide de la façon dont Spring Boot prend en charge JMS

DDD
DDDoriginal
2024-11-02 10:30:03231parcourir

Quick look on how Spring Boot supports JMS

Exemple de code

L'exemple de code provient d'ici avec quelques modifications. Au moment de l'écriture, Spring Boot 3.3.0 (Spring Framework 6.1.8) est utilisé.

complete/pom.xml

Passer au courtier intégré ActiveMQ

<dependency>
    <groupId>org.springframework.boot</groupId>
    <!--<artifactId>spring-boot-starter-artemis</artifactId>-->
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.activemq</groupId>
    <!--<artifactId>artemis-jakarta-server</artifactId>-->
    <artifactId>activemq-broker</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- ... -->

complete/src/main/resources/application.properties

Activez la journalisation du débogage et configurez l'URL du courtier intégré

#spring.artemis.mode=embedded
debug=true
spring.activemq.broker-url=vm://localhost?broker.persistent=false

complete/src/main/java/hello/Application.java

Utilisez le bean JmsListenerContainerFactory créé par Spring Boot plutôt que construit par le nôtre

@SpringBootApplication
@EnableJms
public class Application {

    /*@Bean
    public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all auto-configured defaults to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some settings if necessary.
        return factory;
    }*/

    //...

}

complete/src/main/java/hello/Receiver.java

Spécifiez la valeur par défaut JmsListenerContainerFactory

@Component
public class Receiver {

    //@JmsListener(destination = "mailbox", containerFactory = "myFactory")
    @JmsListener(destination = "mailbox")
    public void receiveMessage(Email email) {
        System.out.println("Received <" + email + ">");
    }

}

Journal de configuration automatique Spring Boot

Seule la configuration liée à JMS est affichée.

   ActiveMQAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'jakarta.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
      - @ConditionalOnMissingBean (types: jakarta.jms.ConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

   ActiveMQAutoConfiguration#activemqConnectionDetails matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails; SearchStrategy: all) did not find any beans (OnBeanCondition)

   ActiveMQConnectionFactoryConfiguration matched:
      - @ConditionalOnMissingBean (types: jakarta.jms.ConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

   ActiveMQConnectionFactoryConfiguration.SimpleConnectionFactoryConfiguration matched:
      - @ConditionalOnProperty (spring.activemq.pool.enabled=false) matched (OnPropertyCondition)

   ActiveMQConnectionFactoryConfiguration.SimpleConnectionFactoryConfiguration.CachingConnectionFactoryConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.jms.connection.CachingConnectionFactory' (OnClassCondition)
      - @ConditionalOnProperty (spring.jms.cache.enabled=true) matched (OnPropertyCondition)

   JmsAnnotationDrivenConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.jms.annotation.EnableJms' (OnClassCondition)

   JmsAnnotationDrivenConfiguration#jmsListenerContainerFactory matched:
      - @ConditionalOnSingleCandidate (types: jakarta.jms.ConnectionFactory; SearchStrategy: all) found a single bean 'jmsConnectionFactory'; @ConditionalOnMissingBean (names: jmsListenerContainerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JmsAnnotationDrivenConfiguration#jmsListenerContainerFactoryConfigurer matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JmsAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'jakarta.jms.Message', 'org.springframework.jms.core.JmsTemplate' (OnClassCondition)
      - @ConditionalOnBean (types: jakarta.jms.ConnectionFactory; SearchStrategy: all) found bean 'jmsConnectionFactory' (OnBeanCondition)

   JmsAutoConfiguration.JmsTemplateConfiguration#jmsTemplate matched:
      - @ConditionalOnSingleCandidate (types: jakarta.jms.ConnectionFactory; SearchStrategy: all) found a single bean 'jmsConnectionFactory'; @ConditionalOnMissingBean (types: org.springframework.jms.core.JmsOperations; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JmsAutoConfiguration.MessagingTemplateConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.jms.core.JmsMessagingTemplate' (OnClassCondition)

   JmsAutoConfiguration.MessagingTemplateConfiguration#jmsMessagingTemplate matched:
      - @ConditionalOnSingleCandidate (types: org.springframework.jms.core.JmsTemplate; SearchStrategy: all) found a single bean 'jmsTemplate'; @ConditionalOnMissingBean (types: org.springframework.jms.core.JmsMessageOperations; SearchStrategy: all) did not find any beans (OnBeanCondition)

Interface associée

Interface Function
org.springframework.jms.support.destination.DestinationResolver lookup jakarta.jms.Destination instance by String name
org.springframework.transaction.jta.JtaTransactionManager control transaction by JTA
org.springframework.jms.support.converter.MessageConverter serialize/deserialize DTO instance
jakarta.jms.ExceptionListener processor when jakarta.jms.JMSException throws. One implementation is SingleConnectionFactory, connection managed by that class will be restarted once exception is catched
io.micrometer.observation.ObservationRegistry for statistics

À propos de ConnectionFactory

L'implémentation d'ActiveMQ est org.apache.activemq.ActiveMQConnectionFactory, mais Spring Framework ne l'utilise pas directement. La classe est enveloppée par org.springframework.jms.connection.CachingConnectionFactory pour le suivi

  • une seule Connexion est créée et celle-ci sera réutilisée
  • cache MessageProducer et MessageConsumer (Dans cet exemple, seul MessageProducer est mis en cache)

Éditeur

Envoi d'un message via org.springframework.jms.core.JmsTemplate

<dependency>
    <groupId>org.springframework.boot</groupId>
    <!--<artifactId>spring-boot-starter-artemis</artifactId>-->
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.activemq</groupId>
    <!--<artifactId>artemis-jakarta-server</artifactId>-->
    <artifactId>activemq-broker</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- ... -->
Le bean

JmsTemplate est construit par org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration.JmsTemplateConfiguration#jmsTemplate. Un bean MessageConverter est nécessaire pour désérialiser le DTO.

DestinationResolver utilisé est org.springframework.jms.support.destination.DynamicDestinationResolver, la classe obtient simplement l'instance de jakarta.jms.Destination en appelant jakarta.jms.Session#createTopic ou jakarta.jms.Session#createQueue.

Abonné

Annotation org.springframework.jms.annotation.JmsListener

attribute Function
id prefix of thread name which run listener
containerFactory bean name of JmsListenerContainerFactory instance
destination the destination name for this listener
subscription the name of the durable subscription, if any
selector an optional message selector for this listener
concurrency number of thread running listener

Classe org.springframework.jms.listener.DefaultMessageListenerContainer

Dans la spécification JMS, le traitement asynchrone des messages est pris en charge et l'écouteur s'exécute sous les threads du fournisseur JMS.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <!--<artifactId>spring-boot-starter-artemis</artifactId>-->
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.activemq</groupId>
    <!--<artifactId>artemis-jakarta-server</artifactId>-->
    <artifactId>activemq-broker</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- ... -->

Mais les approches asynchrones ne sont pas utilisées dans Spring Framework, une API synchrone (polling) est utilisée. Le code réel se trouve dans org.springframework.jms.support.destination.JmsDestinationAccessor#receiveFromConsumer.

#spring.artemis.mode=embedded
debug=true
spring.activemq.broker-url=vm://localhost?broker.persistent=false
La classe

org.springframework.jms.listener.DefaultMessageListenerContainer.AsyncMessageListenerInvoker permet d'effectuer des tâches d'interrogation périodiques. Ceci est programmé dans org.springframework.core.task.SimpleAsyncTaskExecutor.

Une instance DefaultMessageListenerContainer est créée pour une fonction annotée @JmsListener. Ceci est produit par org.springframework.jms.config.DefaultJmsListenerContainerFactory.

Bien sûr, les instances MessageConverter et ExceptionListener sont nécessaires.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn