applicationContext.xml
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.1.0.xsd">
......
<!-- Embedded ActiveMQ Broker -->
<amq:broker id="broker" useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:61617" />
</amq:transportConnectors>
</amq:broker>
<import resource="classpath:activemq-properties.xml" />
<import resource="classpath:activemq-jms.xml" />
</beans>
这里引入了activemq-properties.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jmsProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
name="jmsProperties">
<property name="order" value="99999" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="properties">
<value>
<!-- JMS -->
JMS.BROKER.URL=tcp://localhost:61617
JMS.QUEUE.NAME1=IN_QUEUE1
JMS.QUEUE.NAME2=IN_QUEUE2
</value>
</property>
</bean>
</beans>
和activemq-jms.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- ActiveMQ connection factory -->
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="${JMS.BROKER.URL}" />
</bean>
<!-- ConnectionFactory Definition -->
<bean id="connectionFactory1"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="sessionCacheSize" value="10"></property>
</bean>
<bean id="connectionFactory2"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="sessionCacheSize" value="10"></property>
</bean>
<!-- Destination Queue -->
<bean id="destinationQueue1" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="${JMS.QUEUE.NAME1}" />
</bean>
<bean id="destinationQueue2" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="${JMS.QUEUE.NAME2}" />
</bean>
<!-- Message converter -->
<bean id="messageConv" class="com.sap.c4c.wechat.jms.MessageConverter"><!--自定义的消息转换器-->
</bean>
<!-- JmsTemplate Definition -->
<!--<bean id="jmsTemplate1" class="com.sap.c4c.wechat.jms.MessageJmsTemplate">--><!--自定义的消息JMS模板,但其实没有必要,可以像下面两个那样-->
<!--<property name="connectionFactory" ref="connectionFactory1" />-->
<!--<property name="defaultDestination" ref="destinationQueue1" />-->
<!--<property name="messageConverter" ref="messageConv"></property>-->
<!--</bean>-->
<bean id="jmsTemplate1" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory1" />
<property name="defaultDestination" ref="destinationQueue1" />
<property name="messageConverter" ref="messageConv"></property>
</bean>
<bean id="jmsTemplate1_b" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory1" />
<property name="defaultDestination" ref="destinationQueue1" />
<property name="messageConverter" ref="messageConv"></property>
</bean>
<bean id="jmsTemplate2" class="com.sap.c4c.wechat.jms.MessageJmsTemplate">
<property name="connectionFactory" ref="connectionFactory2" />
<property name="defaultDestination" ref="destinationQueue2" />
<property name="messageConverter" ref="messageConv"></property>
</bean>
<!-- Message Producer -->
<bean id="messageProducer1" class="com.sap.c4c.wechat.jms.MessageProducer1" ><!--第一种消息生产者-->
<!--<property name="jmsTemplate">--><!--这里不定义,在类中定义-->
<!--<list>-->
<!--<ref bean="jmsTemplate_1" />-->
<!--<ref bean="jmsTemplate_2" />-->
<!--</list>-->
<!--</property>-->
</bean>
<bean id="messageProducer2" class="com.sap.c4c.wechat.jms.MessageProducer2" /><!--第二种消息生产者-->
<!-- Message Consumer -->
<bean id="messageConsumer1" class="com.sap.c4c.wechat.jms.MessageConsumer1" /><!--第一种消息消费者-->
<bean id="messageConsumer2" class="com.sap.c4c.wechat.jms.MessageConsumer2" /><!--第二种消息消费者-->
<!-- Message Consumer Container -->
<bean id="container1"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"><!--第一套消息传送-->
<property name="connectionFactory" ref="connectionFactory1" />
<property name="destinationName" value="${JMS.QUEUE.NAME1}" />
<property name="messageListener" ref="messageConsumer1" />
</bean>
<bean id="container2"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"><!--第二套消息传送,这里允许多个第二种消费者-->
<property name="connectionFactory" ref="connectionFactory2" />
<property name="destinationName" value="${JMS.QUEUE.NAME2}" />
<property name="messageListener" ref="messageConsumer2" />
<!-- 配置多个消费者,可以是具体数值,也可以是数值区间,根据消息的规模来确定消费者的多少 -->
<property name="concurrency" value="4-8"></property>
</bean>
</beans>
它们都放在src/main/resources下
pom.xml相关部分
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.7</version>
</dependency>
MessageJmsTemplate
public class MessageJmsTemplate extends org.springframework.jms.core.JmsTemplate{
}
MessageConverter
import org.springframework.jms.support.converter.MessageConversionException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import java.io.Serializable;
public class MessageConverter implements org.springframework.jms.support.converter.MessageConverter{
@Override
public Message toMessage(Object o, Session session) throws JMSException, MessageConversionException {
Message message=session.createObjectMessage((Serializable) o);
int group=Integer.parseInt(((com.sap.c4c.wechat.model.Message)o).getContent());
message.setStringProperty("JMSXGroupID","group"+group);
// message.setIntProperty("JMSXGroupSeq", -1);
return message;
}
@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
ObjectMessage objMessage = (ObjectMessage) message;
return objMessage.getObject();
}
}
MessageProducer1
import com.sap.c4c.wechat.model.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import java.util.logging.Logger;
public class MessageProducer1 {
private static final Logger logger = Logger.getLogger(MessageProducer1.class.getName());
@Autowired
private JmsTemplate jmsTemplate1;
@Autowired
private JmsTemplate jmsTemplate1_b;
public void sendMessageToDefaultDestination(Message message) {
logger.info("producer1: "+message.getContent());
if(Integer.parseInt(message.getContent())%3==0) {
message.setContent(message.getContent() + "_b");
jmsTemplate1_b.convertAndSend(message);
}else
{
jmsTemplate1.convertAndSend(message);
}
}
}
MessageProducer2
import com.sap.c4c.wechat.model.Message;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.logging.Logger;
public class MessageProducer2 {
private static final Logger logger = Logger.getLogger(MessageProducer2.class.getName());
@Autowired
private MessageJmsTemplate jmsTemplate2;
public void sendMessageToDefaultDestination(Message message) {
logger.info("producer2: "+message.getContent());
jmsTemplate2.convertAndSend(message);
}
}
MessageConsumer1
import com.sap.c4c.wechat.model.Message;
import com.sap.c4c.wechat.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.logging.Logger;
public class MessageConsumer1 implements MessageListener {
private static final Logger logger = Logger.getLogger(MessageConsumer1.class.getName());
@Autowired
MessageService messageService;
@Override
public void onMessage(javax.jms.Message message) {
try {
ObjectMessage objMessage=(ObjectMessage) message;
Object obj = objMessage.getObject();
Message wechatMessage = (Message) obj;
//TODO
logger.info("consumer1: "+wechatMessage.getContent()+" thread-"+Thread.currentThread().getName());
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}
MessageConsumer2
import com.sap.c4c.wechat.model.Message;
import com.sap.c4c.wechat.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.logging.Logger;
public class MessageConsumer2 implements MessageListener {
private static final Logger logger = Logger.getLogger(MessageConsumer2.class.getName());
@Autowired
MessageService messageService;
@Override
public void onMessage(javax.jms.Message message) {
try {
ObjectMessage objMessage=(ObjectMessage) message;
Object obj = objMessage.getObject();
Message wechatMessage = (Message) obj;
//TODO
logger.info("consumer2: "+wechatMessage.getContent()+" thread-"+Thread.currentThread().getName());
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}
MessageController
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import io.swagger.annotations.Api;
import org.apache.commons.io.IOUtils;
import org.apdplat.word.WordSegmenter;
import org.apdplat.word.segmentation.Word;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
@RestController("ControllerV1")
@RequestMapping("/v1/message")
@Api(value="Message")
public class MessageController extends GenericController<MessageDTO, Message> {//这里的Message是一个Model,有String类型的content成员
private static final Logger logger = LoggerFactory.getLogger(MessageController.class.getName());
@Autowired
private MessageProducer1 messageProducer1;
@Autowired
private MessageProducer2 messageProducer2;
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public void test(@PathVariable int id) throws Exception
{
Message message=new Message();
message.setContent(id+"");
if(id%2!=0)//odd
messageProducer1.sendMessageToDefaultDestination(message);
else//even
messageProducer2.sendMessageToDefaultDestination(message);
}
}
这样模拟实现了多个queue,多个consumer的ActiveMQ
MessageConverter使用了消息的分组,运行发现JMSGroupID相同的总是在同一个线程(同一个Consumer2)中处理。
参考链接:
http://www.jeejava.com/embedded-activemq-and-spring-jms-integration/
http://activemq.apache.org/features.html
http://activemq.apache.org/message-groups.html
http://activemq.apache.org/spring-support.html
http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html
http://elim.iteye.com/blog/1900937
http://isoftyh.iteye.com/blog/1774015
https://stackoverflow.com/questions/18802982/no-declaration-can-be-found-for-element-contextannotation-config
http://coderbase64.iteye.com/blog/2065528
https://codedependents.com/2009/10/16/efficient-lightweight-jms-with-spring-and-activemq/
http://www.blogjava.net/ldd600/archive/2010/11/02/336755.html
https://stackoverflow.com/questions/30183907/activemq-how-to-programmatically-monitor-embedded-broker
http://blog.csdn.net/u010248330/article/details/62429001
http://www.360doc.com/content/16/0406/18/203871_548376577.shtml
http://www.bubuko.com/infodetail-2065759.html