最近开始尝试使用消息中间件,本来想对比一下ActiveMQ(Artemis)和RocketMQ,自己简单撸了一遍官方文档,感觉两个MQ的原理差别不大。
Artemis更倾向于突出它能支持各种协议,比如JMS,AMQP,STOMP, MQTT等。而RocketMQ是阿里开源的,更倾向于高并发下的可用性、处理性能。由于时间有限,正好搭建了一套ActiveMQ的测试环境,所以就直接使用ActiveMQ进行尝试,写了第一个Demo。
从DEMO的代码来看,还是比较简单的,与Spring集成也不复杂,但是过程确实遇到一些坑。没有很直接的文档可供使用,官方给的sample也都是片段式的,也都是基于spring boot的。对于spring xml配置型的使用方式,还是花了些时间从网上找资料,所以简单记录一下(本示例使用了Spring的JMSTemplate来进行connection)。
1、引入相关包
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
2、spring context配置文件中配置所需要的bean对象
<!-- Active MQ Artemis -->
<!-- 连接工厂类 -->
<bean id="mqConnectionFactory"
class="org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory">
<constructor-arg value="${mq.uri}"></constructor-arg>
<property name="user" value="${mq.username}"></property>
<property name="password" value="${mq.password}"></property>
<!-- 消息消费时不进行缓存,每次取一个 -->
<property name="consumerWindowSize" value="0"></property>
</bean>
<!-- 缓存JMS连接工厂 -->
<bean id="cachingMqConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="mqConnectionFactory"></property>
</bean>
<!-- jms消息转换器 -->
<bean id="mqMessageConverter" class="com.spring.xx.platform.mq.MqMessageConverter"></bean>
<!-- 点对点 消息发送模板 -->
<bean id="pointJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="cachingMqConnectionFactory"></constructor-arg>
<!-- 定义默认Queue -->
<property name="defaultDestinationName" value="xx::dd.notice"></property>
<!-- 点对点模式 -->
<property name="pubSubDomain" value="false"></property>
<!-- 转换器 -->
<property name="messageConverter" ref="mqMessageConverter"></property>
</bean>
<!-- 消息接受监听器(文本消息) -->
<bean id="textReceiveListener" class="com.spring.xx.platform.mq.TextReceiveListener"></bean>
<bean id="defaultMessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="messageListener" ref="textReceiveListener"></property>
<property name="destinationName" value="xx::dd.notice"></property>
<property name="connectionFactory" ref="cachingMqConnectionFactory"></property>
<property name="messageConverter" ref="mqMessageConverter"></property>
</bean>
<!-- END Active MQ Artemis -->
3、消息创建(producer)
@Controller
@RequestMapping(value = "/test")
public class JmsTestController {
@Autowired
@Qualifier("pointJmsTemplate")
private JmsTemplate jmsTemplate;
@RequestMapping("/sendJms")
@ResponseBody
public String send() {
jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("发送消息:" + System.currentTimeMillis());
}
});
return "hello";
}
}
@RequestMapping("/sendJmsEntity")
@ResponseBody
public String sendEntity() {
MqSettleNoticeEntity entity = new MqSettleNoticeEntity();
entity.setFundCode("xx");
entity.setAsOfDate(20210101);
jmsTemplate.convertAndSend(entity);
return "hello entity";
}
4、消息接收处理(consumer)
@Component
public class TextReceiveListener implements MessageListener {
@Override
public void onMessage(Message message) {
try {
System.out.println("-----Receive Message:" + ((TextMessage) message).getText());
Thread.sleep(10000);
} catch (InterruptedException | JMSException e) {
e.printStackTrace();
}
}
}
@Override
public void onMessage(Message message) {
try {
System.out.println("-----Receive Message:" + (MqSettleNoticeEntity) ((ObjectMessage) message).getObject());
Thread.sleep(10000);
} catch (InterruptedException | JMSException e) {
e.printStackTrace();
}
}
4、定义消息转换器(如果直接发送文本消息(如示例代码里的sendJms)可以不需要转换器)
public class MqMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object o, Session session) throws JMSException, MessageConversionException {
return session.createObjectMessage((Serializable) o);
}
@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
return ((ObjectMessage) message).getObject();
}
}
参考资料: