Spring Integration系列《3》JMS ActiveMQ实列

源码地址

https://gitee.com/bseaworkspace/study_java_web/tree/master/springIntegrationJMS

说明

  • JMS ActiveMQ 服务器有两种方式
  1. 下载((http://activemq.apache.org/download.html))ActiveMQ 压缩包,解压以后运行其bin目录下面的activemq.bat文件启动activeMQ。
  2. 直接使用内置的 ActiveMQ(EmbbededActiveMQ),这个直接随着Spring启动,自动启动一个内置的ActiveMQ JMS 服务。
  • 本案例,使用了内置的ActiveMQ,所以不需要额外下载和启动ActiveMQ

代码使用方式

提供了三个测试用例,分别测试了

  • GatewayDemo 结合SpringIntegration的channel-adapter 实现点对点的JMS通信实列

uses the DemoBean service, which will echo the response and
upper-casing it.

  • ChannelAdapterDemo 结合SpringIntegration的inbound-gateway和outbound-gateway 实现点对点的JMS通信实列

will simply echo the response

  • AggregatingDemo .结合SpringIntegration的inbound-gateway和outbound-gateway 实现点对点和订阅者模式的JMS通信实列

uses a JMS Topic; and aggregates the responses from two inbound
gateways, which invoke a flow that upper-cases the response; the
aggregation returns a list of responses

在这里插入图片描述

本实列 使用到的Spring Integration知识

  • Spring Integration 主要解决的问题是不同系统之间交互的问题,通过异步消息驱动来达到系统交互时系统之间的松耦合。
  • Spring Inegration 主要三部分组成 Message(消息), Channel(传递消息的管道), Message EndPoint(正在处理消息的组件)

脑图地址:
http://naotu.baidu.com/file/272eb7e9ff11511f831c394baeb76302?token=06add75ef19ec173

在这里插入图片描述

  • Message 一共由两部分组成,我们一般把信息放在payload上。

在这里插入图片描述

  • 每个Message都必须通过Channel来传递,消息发送者发送消息到通道(Channel),消息接受者从通道(Channel)接收消息。
    MessageChannel 有两大子接口,分别是PollableChannel (可轮询)和SubscribableChannel(可订阅)。我们所有的消息通道类都是现实这两个接口。

在这里插入图片描述

  • 适配器(Channel Adapter)可以设置channel的方向。 比如 message是 包裹,那么channel就是快递员负责运送包裹,适配器就是包裹的快递站,快递员是要把包裹放到本地的收件人家里,还是要帮忙把包裹寄到外地出去,都是快递站决定的,所以适配器决定了channel的方向。

通道适配器(Channel
Adapter)是一种连接外部系统或传输协议的端点(EndPoint),可以分为入站(inbound)和出站(outbound)。
通道适配器是单向的,入站通道适配器只支持接收消息,出站通道适配器只支持输出消息。

Spring Integration内置了如下的适配器:

RabbitMQ、Feed、File、FTP/SFTP、Gemfire、HTTP、TCP/UDP、JDBC、JPA、JMS、Mail、MongoDB、Redis、RMI
Twitter、XMPP、WebServices(SOAP、REST)、WebSocket

在这里插入图片描述

  • 消息网关(Gateway)类似于Adapter,但是提供了双向的请求/返回集成方式,也分为入站(inbound)和出站(outbound)。
    Spring Integration 对响应的Adapter都提供了Gateway。

ActiveMQ的相关概念

1.Destination

目的地,JMS Provider(消息中间件)维护,用于对Message进行管理的对象。

MessageProducer需要指定Destination才能发送消息,MessageConsumer需要指定Destination才能接收消息。

2.Producer

消息生成者(客户端,生成消息),负责发送Message到目的地。应用接口为MessageProducer

3.Consumer【Receiver】

消息消费者(处理消息),负责从目的地中消费【处理|监听|订阅】Message。应用接口为MessageConsumer

4.Message

消息(Message),消息封装一次通信的内容。常见类型有:StreamMessage、BytesMessage、TextMessage、ObjectMessage、MapMessage。

5.ConnectionFactory 链接工厂, 用于创建链接的工厂类型。 注意,不能和 JDBC 中的 ConnectionFactory 混 淆。

6.Connection 链接. 用于建立访问 ActiveMQ 连接的类型, 由链接工厂创建. 注意,不能和 JDBC 中的 Connection 混淆。

7.Session 会话, 一次持久有效有状态的访问. 由链接创建. 是具体操作消息的基础支撑。

8.Queue&Topic

Queue是队列目的地,Topic是主题目的地。都是Destination的子接口。

Queue特点:队列中的消息,默认只能有唯一的一个消费者处理。

Topic特点:主题中的消息,会发送给所有的消费者同时处理。只有在消息可以重复处理的业务场景中可使用。

9.PTP

Point to Point。点对点消息模型,就是基于Queue实现的消息处理方式。

10.PUB&SUB

Publish&Subscribe。消息的发布/订阅模型。是基于Topic实现的消息处理方式

源码解析

  • 关于DefaultMessageListenerContainer

在Spring框架中使用JMS传递消息有两种方式:JMS template和message listener container,前者用于同步收发消息,后者用于异步收发消息。

message listener container绑定连接类工厂(connection factory)、JMS Destination、JNDI Destination解析器和message listener bean。

Spring提供了两种message listener container:DefaultMessageListenerContainer和SimpleMessageListenerContainer。两种message listener container都允许指定数量的并发监听线程,只有DefaultMessageListenerContainer可以在允许期间动态调整监听线程的数量。另外,DefaultMessageListenerContainer允许和XA Transactions的集成。对于使用本地事务管理器和不需要基于可变负载的线程、会话、连接调整的简单消息传递应用,使用SimpleMessageListenerContainer。对于使用外部事务管理器或XA事务的消息传递应用,使用DefaultMessageListenerContainer。
message listener container的配置类似JmsTemplate。使用JNDI访问连接工厂和JMS Destinations,
或直接使用JMS提供者的native 连接工厂和JMS destination类。




package com.xsz;

import java.util.List;
import java.util.Map;

import org.junit.Assert;
import org.junit.Test;

import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;

/**
 * @author Gunnar Hillert
 * @author Gary Russell
 * @author Artem Bilan
 */
public class AggregatorDemoTest {

    private final static String[] configFilesGatewayDemo = {
            "/META-INF/spring/integration/common.xml",
            "/META-INF/spring/integration/aggregation.xml"
    };

    @Test
    public void testGatewayDemo() throws InterruptedException {

        System.setProperty("spring.profiles.active", "testCase");

        final GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext(
                configFilesGatewayDemo);
        Map<String, DefaultMessageListenerContainer> containers = applicationContext
                .getBeansOfType(DefaultMessageListenerContainer.class);
        // wait for containers to subscribe before sending a message.
        containers.values().forEach(c -> {
            int n = 0;
            while (n++ < 100 && !c.isRegisteredWithDestination()) {
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            if (!c.isRegisteredWithDestination()) {
                throw new IllegalStateException("Container failed to subscribe to topic");
            }
        });

        final MessageChannel stdinToJmsOutChannel = applicationContext.getBean("stdinToJmsOutChannel", MessageChannel.class);

        stdinToJmsOutChannel.send(MessageBuilder.withPayload("jms test").build());

        final QueueChannel queueChannel = applicationContext.getBean("queueChannel", QueueChannel.class);

        @SuppressWarnings("unchecked")
        Message<List<String>> reply = (Message<List<String>>) queueChannel.receive(20_000);
        Assert.assertNotNull(reply);
        List<String> out = reply.getPayload();

        Assert.assertEquals("[JMS TEST, JMS TEST]", out.toString());

        applicationContext.close();
    }

}

Spring Integration系列
《1》Hello World项目
https://blog.csdn.net/h356363/article/details/112076788
《2》 http项目
https://blog.csdn.net/h356363/article/details/112120991
更多资料关注微信公众平台
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/h356363/article/details/112398340