ActiveMq整合Spring

z1340954953發表於2018-07-27

ActiveMq-config.xml檔案建立

<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:amq="http://activemq.apache.org/schema/core"
        xmlns:jms="http://www.springframework.org/schema/jms"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
          http://www.springframework.org/schema/jms
          http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
         http://activemq.apache.org/schema/core
         http://activemq.apache.org/schema/core/activemq-core-5.9.0.xsd
         ">

 配置ConnectionFactory

connectionFactory是Spring用於建立到JMS伺服器連結的,Spring提供了多種connectionFactory,我們介紹兩個SingleConnectionFactory和CachingConnectionFactory。

SingleConnectionFactory:對於建立JMS伺服器連結的請求會一直返回同一個連結,並且會忽略Connection的close方法呼叫。

CachingConnectionFactory:繼承了SingleConnectionFactory,所以它擁有SingleConnectionFactory的所有功能,同時它還新增了快取功能,它可以快取Session、MessageProducer和MessageConsumer。我們使用CachingConnectionFactory來作為示例。

<!-- ActiveMq的連線工廠,真正產生ConnectionFactory的地方,由廠商提供 -->
<amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://19.19.19.194:61616" userName="admin" password="admin" ></amq:connectionFactory>
<!-- 或者 
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
	<property name="brokerURL" value="tcp://19.19.19.194:61616"></property>
</bean>
-->
<!-- Spring管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
	<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
	<!-- session快取的數量 -->
	<property name="sessionCacheSize" value="20"></property>
</bean> 

 Spring提供的ConnectionFactory只是Spring用於管理ConnectionFactory的,真正產生到JMS伺服器連結的ConnectionFactory還得是由JMS服務廠商提供,並且需要把它注入到Spring提供的ConnectionFactory中。

配置生產者

配置好ConnectionFactory之後我們就需要配置生產者。生產者負責產生訊息併傳送到JMS伺服器。但是我們要怎麼進行訊息傳送呢?通常是利用Spring為我們提供的JmsTemplate類來實現的,所以配置生產者其實最核心的就是配置訊息傳送的JmsTemplate。對於訊息傳送者而言,它在傳送訊息的時候要知道自己該往哪裡發,為此,我們在定義JmsTemplate的時候需要注入一個Spring提供的ConnectionFactory物件。

在利用JmsTemplate進行訊息傳送的時候,我們需要知道傳送哪種訊息型別:一個是點對點的ActiveMQQueue,另一個就是支援訂閱/釋出模式的ActiveMQTopic。如下所示:

<!-- Spring JmsTemplate 的訊息生產者 start-->
    <!-- 定義JmsTemplate的Queue型別 -->
    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory物件 -->  
        <constructor-arg ref="connectionFactory" />
        <!-- 非pub/sub模型(釋出/訂閱),即佇列模式 -->
        <property name="pubSubDomain" value="false" />
    </bean>

    <!-- 定義JmsTemplate的Topic型別 -->
    <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
         <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory物件 -->  
        <constructor-arg ref="connectionFactory" />
        <!-- pub/sub模型(釋出/訂閱) -->
        <property name="pubSubDomain" value="true" />
    </bean>
<!-- Spring JmsTemplate 的訊息生產者 end-->

配置消費者

生產者往指定目的地Destination傳送訊息後,接下來就是消費者對指定目的地的訊息進行消費了。那麼消費者是如何知道有生產者傳送訊息到指定目的地Destination了呢?每個消費者對應每個目的地都需要有對應的MessageListenerContainer。對於訊息監聽容器而言,除了要知道監聽哪個目的地之外,還需要知道到哪裡去監聽,也就是說它還需要知道去監聽哪個JMS伺服器,通過配置MessageListenerContainer的時候往裡面注入一個ConnectionFactory來實現的。所以我們在配置一個MessageListenerContainer的時候有三個屬性必須指定:一個是表示從哪裡監聽的ConnectionFactory;一個是表示監聽什麼的Destination;一個是接收到訊息以後進行訊息處理的MessageListener

<!-- 訊息消費者 start-->
	<!-- 掃包,建立接受訊息的bean -->
	<context:component-scan base-package="com.activemq" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
	</context:component-scan>
	
	<!-- 定義Queue監聽器 -->
	<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
		<!-- test.queue是建立的佇列的名稱,ref:是訊息接受者Bean的id-->
		<jms:listener destination="test.queue" ref="queueReceiver1"/>
		<jms:listener destination="test.queue" ref="queueReceiver2"/>
	</jms:listener-container>
	
	<!-- 定義Topic監聽器 -->
	<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
		<!-- test.topic是建立的主題名稱,ref:是訊息訂閱者的bean的id -->
		<jms:listener destination="test.topic" ref="topicReceiver1"/>
		<jms:listener destination="test.topic" ref="topicReceiver2"/>
	</jms:listener-container>
<!-- 訊息消費者 end -->      

點對點模型編碼

 傳送者: QueueSender.java

package com.activemq.queue.producer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;

@Component("queueSender")
public class QueueSender {
	@Autowired
	@Qualifier("jmsQueueTemplate")
	private JmsTemplate jmsTemplate;
	public void send(String queueName,final String message){
		jmsTemplate.send(queueName, new MessageCreator() {
			@Override
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage(message);
			}
		});
	}
}

接受者: QueueReceiver1.java,QueueReceiver2.java程式碼是一樣的

package com.activemq.queue.customer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.springframework.stereotype.Component;
@Component("queueReceiver1")
public class QueueReceiver1 implements  MessageListener {
	@Override
	public void onMessage(Message message) {
		TextMessage tm = (TextMessage) message;
		try {
			System.out.println("queueReceiver1獲取的訊息:"+tm.getText());
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}

釋出訂閱模型編碼

釋出者:TopicSender.java

package com.activemq.topic.producer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
@Component("topicSender")
public class TopicSender  {
	@Autowired
	@Qualifier("jmsTopicTemplate")
	private JmsTemplate jmsTemplate;
	public void send(String topicName,final String message){
		jmsTemplate.send(topicName, new MessageCreator() {
			@Override
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage(message);
			}
		});
	}
}

訂閱者:TopReceiver1.java,訂閱者:TopReceiver2.java程式碼一致不在貼出。

package com.activemq.topic.customer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.springframework.stereotype.Component;
@Component("topicReceiver1")
public class TopicReceiver1 implements MessageListener {
	@Override
	public void onMessage(Message message) {
		TextMessage tm = (TextMessage) message;
		try {
			System.out.println("topicReceiver1訂閱的訊息:"+tm.getText());
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}

 controller層呼叫

package cn.bing.controller;

import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.activemq.queue.producer.QueueSender;
import com.activemq.topic.producer.TopicSender;

@Controller
@RequestMapping("/activemq")
public class ActivemqController {
	@Autowired
	private QueueSender queueSender;
	@Autowired
	private TopicSender topicSender;
	@RequestMapping("/queueSender.action")
	@ResponseBody
	public String queueSender(@RequestParam("message")String message){
		String opt="";
		try {
			queueSender.send("test.queue", message);
			opt = "suc";
		} catch (Exception e) {
			opt = e.getCause().toString();
		}
		return opt;
	}
	@RequestMapping("/topicSender.action")
	@ResponseBody
	public String topicSender(@RequestParam("message")String message){
		String opt="";
		try {
			topicSender.send("test.topic", message);
			opt = "suc";
		} catch (Exception e) {
			opt = e.getCause().toString();
		}
		return opt;
	}
}

 web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  	<display-name>zhibing_mybatis</display-name>
  	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:springContext.xml,classpath:activeMq-config.xml</param-value>
  	</context-param>
	<listener>
		<description>spring listener</description>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>*.action</url-pattern>
	</filter-mapping>
	<servlet>
		<description>spring mvc servlet</description>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<description>springmvc config</description>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springMVC.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	
    <welcome-file-list>
    	<welcome-file>index.jsp</welcome-file>
  	</welcome-file-list>
</web-app>

整合中出現的問題

java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

解決方案: lib中加入xbean-spring-4.4.jar

參考文章:

https://blog.csdn.net/wlwlwlwl015/article/details/48134763

https://blog.csdn.net/jiuqiyuliang/article/details/48608237

原始碼下載

相關文章