天天看點

SpringBoot實戰(十一)之與JMS簡單通信

什麼是JMS?

引用百度百科上的說明:

JMS即

Java消息服務 (Java Message Service)應用程式接口,是一個 Java平台 中關于面向 消息中間件 (MOM)的 API ,用于在兩個應用程式之間,或 分布式系統

中發送消息,進行異步通信。Java消息服務是一個與具體平台無關的API,絕大多數MOM提供商都對JMS提供支援。

JMS是一種與廠商無關的 API,用來通路消息收發系統消息,它類似于

JDBC

(Java Database Connectivity)。這裡,JDBC 是可以用來通路許多不同關系資料庫的 API,而 JMS 則提供同樣與廠商無關的通路方法,以通路消息收發服務。許多廠商都支援 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ。 JMS 使您能夠通過消息收發服務(有時稱為消息中介程式或路由器)從一個 JMS 客戶機向另一個 JMS客戶機發送消息。消息是 JMS 中的一種類型對象,由兩部分組成:報頭和消息主體。報頭由路由資訊以及有關該消息的中繼資料組成。消息主體則攜帶着應用程式的資料或有效負載。根據有效負載的類型來劃分,可以将消息分為幾種類型,它們分别攜帶:簡單文本(TextMessage)、可序列化的對象 (ObjectMessage)、屬性集合 (MapMessage)、位元組流 (BytesMessage)、原始值流 (StreamMessage),還有無有效負載的消息 (Message)。

下面進入SpringBoot簡單使用JMS示例:

一、導入依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-messaging-jms</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-broker</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>      

二、編寫消息接收器

package hello;

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());
    }

}      

三、定義消息接收者

package hello;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Receiver {

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

}      

Receiver

也被稱為消息驅動的POJO。正如您在上面的代碼中所看到的,不需要實作任何特定的接口或方法具有任何特定的名稱。此外,該方法可以具有

非常靈活的簽名

。請特别注意,此類在JMS API上沒有導入。

四、使用Spring發送和接收JMS消息

package hello;

import javax.jms.ConnectionFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;

@SpringBootApplication
@EnableJms
public class Application {

    @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(Application.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"));
    }

}      

@Bean注解,主要作用是控制反轉(IOC),同

    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >

    </bean>

舉例說明:

例如以Message為例:

@Bean
public String message() {
    return new String("hello");
}      

它等價于

<bean id="message" class="java.lang.String">
    <constructor-arg index="0" value="hello"/>
</bean>      

通常情況下,有三種配置Bean的方式:

如圖所示

SpringBoot實戰(十一)之與JMS簡單通信

 關于Bean注解三種配置法,深入介紹可以參考該博文:https://blog.csdn.net/icarus_wang/article/details/51649635

@EnableJms

觸發發現帶注釋的方法

@JmsListener

,在封面下建立消息監聽器容器。

為清楚起見,我們還定義了一個在接收器注釋中

myFactory

引用的bean 

JmsListener

。因為我們使用

DefaultJmsListenerContainerFactoryConfigurer

Spring Boot提供的基礎結構,是以

JmsMessageListenerContainer

它與預設情況下引導建立的基礎結構相同。

預設

MessageConverter

是能夠轉換隻有基本類型(例如

String

Map

Serializable

)我們

Email

是不是

Serializable

故意的。我們想要使用Jackson并以文本格式将内容序列化為json(即作為a 

TextMessage

)。Spring Boot将檢測a的存在,

MessageConverter

并将其與預設值

JmsTemplate

和任何

JmsListenerContainerFactory

建立者相關聯

DefaultJmsListenerContainerFactoryConfigurer

JmsTemplate

使消息發送到JMS目的地變得非常簡單。在

main

runner方法中,啟動後,您可以使用

jmsTemplate

發送

Email

POJO。因為我們的自定義

MessageConverter

已自動關聯到它,是以隻會生成一個json文檔

TextMessage

你沒看到的兩個bean是

JmsTemplate

ConnectionFactory

。這些是由Spring Boot自動建立的。在這種情況下,ActiveMQ代理運作嵌入式。

注意:

Spring 

JmsTemplate

可以通過它的

receive

方法直接接收消息,但這隻能同步工作,這意味着它會阻塞。這就是為什麼我們建議您使用偵聽器容器,例如

DefaultMessageListenerContainer

使用基于緩存的連接配接工廠,這樣您就可以異步使用消息并以最大的連接配接效率。

最後運作結果如下圖所示:

SpringBoot實戰(十一)之與JMS簡單通信