SpringBoot使用JMS消息代理

Java Message Service是一个Java标准,它定义了一套与消息broker交互的通用API。在JMS出现之前,每一种消息broker都有自己独特的一套API,使得应用代码无法在不同的broker之间适用。但是通过JMS,所有与broker交互的代码就可以适用一套通用的API,就像JDBC一样。

Spring对JMS也提供了支持,即JmsTemplate。通过JmsTemplate,我们可以更加方便地向queue和topic发送和接收消息。

本次练习使用JMS代理发布和订阅消息的过程。下面构建一个使用Spring JmsTemplate发布单个消息的应用程序,并使用@JmsListener托管bean的带注释方法对其进行订阅。

参考文档:https://spring.io/guides/gs/messaging-jms/

使用Maven 引入依赖如下:

    
        
            org.springframework.boot
            spring-boot-starter-activemq
        
        
            org.apache.activemq
            activemq-broker
        

        
            com.fasterxml.jackson.core
            jackson-databind
        
    

创建一个简单的消息实体类,包含两个字段to和body,以及getter和setter集合,并重写了toString方法:

public class Email {

    private String to;
    private String body;

    public Email() {
    }

    public Email(String to, String body) {
        this.to = to;
        this.body = body;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    @Override
    public String toString() {
        return String.format("Email{to=%s, body=%s}", getTo(), getBody());
    }

}

再定义一个消息接收者,它是消息驱动的类,不需要实现任何特定的接口或具有任何特定名称的方法。JmsListener注解定义的名称destination,表示该方法要参照JmsListenerContainerFactory去使用创建基础消息侦听容器。严格地说,除非需要自定义容器的构建方式,否则不需要最后一个属性,因为Spring Boot会在必要时注册默认工厂。

@Component
public class Receiver {

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

}

接下来,使用SpringBoot启动发送消息和消息接收器,启动类:

@SpringBootApplication
@EnableJms
public class SpringBootJmsApplication {

    
    @Bean
    public JmsListenerContainerFactory myFactory(ConnectionFactory connectionFactory,
                                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all boot's default to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some of Boot's default if necessary.
        return factory;
    }

    @Bean // Serialize message content to json using TextMessage
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }

    public static void main(String[] args) {
        // Launch the application
        ConfigurableApplicationContext context = SpringApplication.run(SpringBootJmsApplication.class, args);

        JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);

        // Send a message with a POJO - the template reuse the message converter
        System.out.println("Sending an email message.");
        jmsTemplate.convertAndSend("mailbox", new Email("[email protected]", "Hello"));
    }
    
}

启动项目,收到消息如下:
Sending an email message.
Received

@EnableJms触发发现带注释的方法@JmsListener,创建消息监听器容器。这里还定义了一个在接收器注释中myFactory引用的bean JmsListener。因为我们使用DefaultJmsListenerContainerFactoryConfigurerSpring Boot提供的基础结构,所以JmsMessageListenerContainer它与默认情况下引导创建的基础结构相同。

默认MessageConverter能够转换只有基本类型(例如String,Map,Serializable),这里Email类是故意不实现序列化的。要使用Jackson并以文本格式将内容序列化为json(即作为一个TextMessage)。Spring Boot将检测MessageConverter的存在,并将其与默认的JmsTemplate和DefaultJmsListenerContainerFactoryConfigurer创建的任何JmsListenerContainerFactory相关联。

JmsTemplate使消息发送到JMS目的地变得非常简单。在main 运行方法中,启动后,可以使用jmsTemplate发送EmailPOJO。因为我们的自定义MessageConverter已自动关联到它,所以只会生成一个json文档TextMessage。JmsTemplate和ConnectionFactory这两个bean是由Spring Boot自动创建的。

Spring JmsTemplate可以通过它的receive方法直接接收消息,但这只能同步工作,这意味着它会阻塞。这就是为什么建议使用侦听器容器,例如DefaultMessageListenerContainer使用基于缓存的连接工厂,这样就可以以最大的连接效率使用异步消息。

你可能感兴趣的:(SpringBoot使用JMS消息代理)