什麼是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的方式:
如圖所示

關于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
使用基于緩存的連接配接工廠,這樣您就可以異步使用消息并以最大的連接配接效率。
最後運作結果如下圖所示: