Spring整合JMS(消息中間件)實例

本篇文章主要描述瞭如何配置Spring-JMS,至於爲何這樣配置及Spring-JMS相關介紹,請閱讀這篇文章:Spring整合JMS(消息中間件)。我們這裏的消息broker用的是ActiveMQ。

一、相關配置

本篇主要講解如何在Spring中配置JMS,關於Spring本身的配置本文就不多做介紹了。

1.1 配置maven依賴

在使用Spring-JMS之前,先配置相關依賴。

<!-- Java JMS 原生API -->
<dependency>
   <groupId>javax.jms</groupId>
   <artifactId>javax.jms-api</artifactId>
   <version>2.0</version>
</dependency>
<!-- spring-jms API -->
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jms</artifactId>
   <version>${spring.version}</version>
</dependency>
<!-- active-mq核心包 -->
<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>activemq-core</artifactId>
   <version>5.7.0</version>
</dependency>
<!-- spring-test類用來測試 -->
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring.version}</version>
</dependency>

 1.2 安裝並啓動ActiveMQ

這裏只是簡單介紹如何安裝啓動ActiveMQ,詳細請參考官方文檔。

  1. 下載ActiveMQ:http://activemq.apache.org/download.html
  2. 安裝:
    - 解壓:tar zxvf activemq-x.x.x-bin.tar.gz
    - 增加權限:
    cd [activemq_install_dir]/bin
    chmod 755 activemq

  3. 啓動:
    cd [activemq_install_dir]/bin
    ./activemq start

  4. 檢查是否啓動成功:
    netstat -nl|grep 61616

我們還可以通過監控頁面查看ActiveMQ運行情況:http://localhost:8161/admin (默認用戶名密碼都是admin)

1. 3 配置JMS相關bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:jms="http://www.springframework.org/schema/jms"
   xmlns:amq="http://activemq.apache.org/schema/core"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans.xsd
                       http://www.springframework.org/schema/context
                       http://www.springframework.org/schema/context/spring-context.xsd
                       http://www.springframework.org/schema/jms
                       http://www.springframework.org/schema/jms/spring-jms.xsd
                       http://activemq.apache.org/schema/core
                       http://activemq.apache.org/schema/core/activemq-core.xsd">

<!-- 配置連接ActiveMQ的ConnectionFactory -->
<bean id="amqConnectionFactory"
      class="org.apache.activemq.ActiveMQConnectionFactory"
      p:brokerURL="tcp://localhost:61616"/>
<!--爲了提高效率,配置一個連接池-->
<bean id="cachedConnectionFactory"
      class="org.springframework.jms.connection.CachingConnectionFactory"
      p:targetConnectionFactory-ref="amqConnectionFactory"
      p:sessionCacheSize="10"/>
<!-- 配置broker的destination-->
<bean id="destination"
      class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="FOO.TEST"/>
</bean>
<!-- 配置Spring的JmsTemplate -->
<bean id="producerTemplate"
      class="org.springframework.jms.core.JmsTemplate"
      p:connectionFactory-ref="cachedConnectionFactory"
      p:defaultDestination-ref="destination"/>
</beans>

從這個配置中可以看到,這裏的配置比Spring整合JMS(消息中間件)文章中介紹的多了一個cachedConnectionFactory配置。我們知道創建和銷燬連接是非常消耗資源的,爲了解決創建銷燬連接帶來的資源消耗,我們一般會引入連接池(Pool)或者緩存(Cache)。普通的JmsTemplate的ConnectionFactory每次發送消息時都需要建立新的連接,這樣效率是非常低的,所以在具體配置時,我們要儘量用到連接池或緩存,所以這裏的配置中加了一個cachedConnectionFactory作爲緩存。

二、發送消息

寫一個JmsMessageProducer異步發送消息:

@Component
public class JmsMessageProducer {
    private static final Logger logger = LoggerFactory.getLogger(JmsMessageProducer.class);
    @Autowired
    protected JmsTemplate jmsTemplate;
    protected int numberOfMessages = 10;

    public void sendMessages() throws JMSException {
        StringBuilder payload = null;
        for (int i = 0; i < numberOfMessages; ++i) {
            payload = new StringBuilder();
            payload.append("Message [").append(i).append("] sent at: ").append(new Date());
            jmsTemplate.convertAndSend(payload.toString());
            logger.info("Sending message number [" + i + "]");
        }
    }
}

三、接收消息

3.1 方式一:寫一個JmsMessageConsumer 同步接收消息

@Component
public class JmsMessageConsumer {
    private static final Logger logger = LoggerFactory.getLogger(JmsMessageProducer.class);
    @Autowired
    private JmsTemplate template;
    public void receiveMessages() throws JMSException {
        Message message =template.receive();
        TextMessage textMessage =(TextMessage)template.receive();
        logger.info(textMessage.getText());
    }
}

3.2 方式二:寫一個JmsMessageListener監聽器異步接收消息

@Component
public class JmsMessageListener implements MessageListener{
    private static final Logger logger = LoggerFactory.getLogger(JmsMessageListener.class);
    public void onMessage(Message message) {
        try {
            TextMessage msg = (TextMessage) message;
            logger.info("Consumed message: " + msg.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

寫完listener之後還需要在配置文件中配置這個listener:

<!-- 注入我們寫的listener -->
<bean id="jmsMessageListener" class="com.heaven.spring.jms.JmsMessageListener"/>

<!-- 配置listener到listener-container當中 -->
<jms:listener-container
        container-type="default"
        connection-factory="cachedConnectionFactory"
        acknowledge="auto">
    <jms:listener destination="FOO.TEST" ref="jmsMessageListener" method="onMessage"/>
</jms:listener-container>

四、測試一下

4.1 測試發送異步消息

寫一個JmsMessageProducerTest測試一下發送:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/root-context.xml")
public class JmsMessageProducerTest {
    @Autowired
    JmsMessageProducer jmsMessageProducer;
    @Test
    public void testSend(){
        try {
            jmsMessageProducer.sendMessages();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

看一下運行結果:

這裏寫圖片描述

消息已經異步發送成功,雖然還沒有消費者消費,消息就像被成功處理一樣。

4.2 測試同步接收消息

寫一個JmsMessageConsumerTest 測試一下接收:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/root-context.xml")
public class JmsMessageConsumerTest {
    @Autowired
    JmsMessageConsumer jmsMessageConsumer;
    @Test
    public void testSend(){
        try {
            jmsMessageConsumer.receiveMessages();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

看一下運行結果:

這裏寫圖片描述

我們可以看到消費者接收到一條消息,這條消息正是上面發送者發送的第一條消息。如果我們再運行一遍則會收到第二條消息。如果所有消息都消費完了,broker中沒有消息了,此時JmsMessageConsumerTest進程便會掛起一直等待,直到有新消息產生,大家可以試一下。

4.3測試一下異步消息接收

按照上面3.2節寫介紹一個JmsMessageListener並將其配置到 listener-container中。此時JmsMessageListener便會實時監聽brokerURL="tcp://192.168.134.128:61616"這個端口,一旦有消息產生,便會在onMessage()方法接收到消息。其實此時我們的producer和監聽器都在同一個應用中,如果我們再運行producer,可以看到如下結果:
這裏寫圖片描述

通過運行結果可以看到,每當生產者生產消息,監聽器便會實時接收到消息。

發佈了98 篇原創文章 · 獲贊 1135 · 訪問量 154萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章