JavaEE- 带有 JMS 和 MDB 的消息传递系统

Posted

技术标签:

【中文标题】JavaEE- 带有 JMS 和 MDB 的消息传递系统【英文标题】:JavaEE- messaging system with JMS and MDB 【发布时间】:2017-10-25 18:40:01 【问题描述】:

我是 JavaEE 的新手,我尝试使用 jms 和 mdb 构建消息传递系统。我想做以下事情: - 由 mdb 实现的用于处理消息的服务器 - 应该沟通的不同客户 - 客户端应该只通过服务器而不是直接通信

所以没什么特别的。我在 oracle 的文档和教程中阅读了很多,但我仍然对某些事情感到困惑(尽管它正在工作)。

1.消息驱动的bean: 在@MessageDriven 注解中可以使用@ActivationConfigProperty 注解配置bean,例如:

@MessageDriven(mappedName = "myBean", activationConfig = 
        @ActivationConfigProperty(propertyName = "messageSelector",
                propertyValue = "requestType = 'reqA' OR requestType = 'reqB'"),
        @ActivationConfigProperty(propertyName = "destinationType",
                propertyValue = "javax.jms.Queue"))

但是我如何“创建”这个 bean 的队列呢?我想我在这里想念一些东西..

2.对于我使用托管 bean 的客户端。客户端能够发送和接收,因此他们需要一个队列或一个主题。我在客户端中创建队列

@Resource(name = "clientQueue")
private Queue clientQueue;

并使用

从 mdb 中获取队列
@Resource(mappedName = "serverBean")
private Queue serverQueue;

在 mdb 中,我从客户端获取队列

 @Resource(name = "clientQueue")
 private Queue clientQueue;

这是正确的还是有更好的解决方案?

我知道这是非常基本的,但我很困惑,因为例如apache tomcat 的教程表单与 oracle 的教程有一些差异,我不明白。

我有点困惑,所以任何澄清都会非常好!

【问题讨论】:

【参考方案1】:

您所指的队列存在于您的应用程序之外,由您的服务器提供访问它们的机制。最简单的场景是你的队列是由你的服务器定义的,使它们很容易被所有运行在那里的应用程序使用。实际定义是特定于提供商的(即在 jboss、payara 等上不同)。

让我们看看如何在 Wildfly/JBoss 上完成它。服务器使用 ActiveMQ 消息传递子系统,我们可以在其中定义连接工厂、队列、主题等。

<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
            <server name="default">
                <security-setting name="#">
                    <role name="guest" send="true" consume="true" create-non-durable-queue="true" delete-non-durable-queue="true"/>
                </security-setting>
                <address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>
                <http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/>
                <http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
                    <param name="batch-delay" value="50"/>
                </http-connector>
                <in-vm-connector name="in-vm" server-id="0"/>
                <http-acceptor name="http-acceptor" http-listener="default"/>
                <http-acceptor name="http-acceptor-throughput" http-listener="default">
                    <param name="batch-delay" value="50"/>
                    <param name="direct-deliver" value="false"/>
                </http-acceptor>
                <in-vm-acceptor name="in-vm" server-id="0"/>
                <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
                <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
                <connection-factory name="InVmConnectionFactory" connectors="in-vm" entries="java:/ConnectionFactory"/>
                <connection-factory name="RemoteConnectionFactory" connectors="http-connector" entries="java:jboss/exported/jms/RemoteConnectionFactory"/>
                <pooled-connection-factory name="activemq-ra" transaction="xa" connectors="in-vm" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory"/>
            </server>
        </subsystem> 

这是 Wildfly 10 上的默认配置(您必须使用完整配置文件,或手动将 messaging-activemq 子系统添加到您的配置文件)。默认配置已经提供了一个本地连接工厂(InVmConnectionFactory)和两个队列——死信队列和到期队列。让我们添加新队列: 每个队列都需要有一个名称和至少一个 jndi 查找条目。

<jms-queue name="ClientQueue" entries="java:/jms/queue/clientQueue"/>

这定义了您的clientQueue 队列,应该满足您通过@Resource(name = "clientQueue") 的查找。

请注意,您的 MDB 还需要额外的配置来指定从哪个队列侦听消息。

@ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/clientQueue")

我建议您从服务器供应商提供的简单示例之一开始。有一些很好的例子 here 和 here。 愉快的黑客攻击。

【讨论】:

以上是关于JavaEE- 带有 JMS 和 MDB 的消息传递系统的主要内容,如果未能解决你的问题,请参考以下文章

一篇博客带你拿下吉林大学JAVAEE期末

一篇博客带你拿下吉林大学JAVAEE期末

MDB 和 JMS 的区别

Wildfly JMS:当消息存在时,MDB bean 空闲

我可以在 MDB 中获取源 JMS 会话吗?

是否可以在运行时手动将消息驱动 bean 订阅到 JMS 队列/主题?