速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

PHP 开发者的 BlazeDS 和 JMS 指南,第二部分

  • 2010-07-19
  • 本文字数:6350 字

    阅读完需:约 21 分钟

本系列的第1 部分主要描述了通过使用BlazeDS 将Java 服务、PHP 以及Adobe Flash Builder 的用户界面与JMS 相集成。文章展示了只需区区几处配置改动,您就可以使用BlazeDS 通过MessageBroker servlet 把Flash Builder 所建立的用户界面与JMS 消息队列相连接。文章还涉及了整合PHP 和Java 及JMS 的另一种方法:使用REST(Representational State Transfer)Web 服务把消息发送到JMS 队列。

本系列的第2 部分则讨论整合PHP 和Java 的另外两个方法。第一种方法——桥接(bridging),让您可以在PHP 中使用Java 对象,从PHP 中通过Java 曝露的方法把消息发送到JMS 消息队列。第二种集成的方法是利用STOMP(Streaming Text Orientated Messaging Protocol)协议与ActiveMQ(JMS 的实现之一)进行通信。当ActiveMQ 接收到消息,ActiveMQ 会把消息放入JMS 队列,Adobe Flex 应用程序则从队列中接收消息。

通过桥接与 PHP集成

本系列的第 1 部分说明了如何使用 BlazeDS 和 JMS 在 Java 与 Flex 之间传递消息。其他技术也能够完成 PHP 与 Java 的集成,让您间接地把消息放入 JMS 队列。 Java/PHP 桥就是这些技术的一种,它允许您使用已配置好的、运行于 ActiveMQ 上的同一个 JMS 队列。使用 Java/PHP 桥,您可以写 PHP 脚本来调用 Java 类中的方法。此方法会把 JMS 消息放入消息队列。Flex 用户界面则使用 BlazeDS 来连接 JMS 队列,从队列中接收消息,正如它在 REST Web 服务中做的那样。

PHP/Java 桥的发布包里面有一个 JavaBridge.war 文件。解压此 WAR 包,把解压后的文件放进 ActiveMQ 的 webapps/JavaBridge 目录下,并在 conf/jetty.xml 配置文件中添加此应用程序。此 JavaBridge Web 应用程序包含了从 PHP 脚本接收消息的 Servlets,处理消息,然后运行 Java 类。

Java 示 **** 例

由于 PHP 脚本和 Java 类之间的通信可能会很慢,因此需创建一个 Java 类,在一个方法中来处理。这种做法就是著名的 Fa?ade 设计模式——在所暴露的简单方法背后隐藏了复杂的功能。

下面是 Java 实例的 Fa?ade 类,类名为 MessageHelper,包名为 com.example.bridge。

复制代码
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.util.IndentPrinter;
public class MessageHelper {
private Destination destination;
private String user = ActiveMQConnection.DEFAULT_USER;
private String password = ActiveMQConnection.DEFAULT_PASSWORD;
public void sendMessage(String url, String subject, String messageText) {
Connection connection = null;
try {
boolean isTopic = true;
boolean isPersistent = false;
System.out.println("Using URL: <" + url + ">");
System.out.println("Using Subject: <" + subject + ">");
System.out.println("Sending Message Text: <" + messageText + ">");
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
if (isTopic) {
destination = session.createTopic(subject);
} else {
destination = session.createQueue(subject);
}
// Create the producer.
MessageProducer producer = session.createProducer(destination);
if (isPersistent) {
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
} else {
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
}
TextMessage message = session.createTextMessage(messageText);
producer.send(message);
System.out.println("Done.");
// Use the ActiveMQConnection interface to dump the connection
// stats.
ActiveMQConnection c = (ActiveMQConnection)connection;
c.getConnectionStats().dump(new IndentPrinter());
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
} finally {
try {
connection.close();
} catch (Throwable ignore) {
}
}
}
}

此 Java 类只有一个方法——sendMessage(),该方法有三个参数:JMS 的目的地 URL 地址、所使用的 Topic 名及消息内容。

把以上写好的类放入一个 JAR 文件中,然后把此 JAR 文件放入 JavaBridge Web 应用程序的 WEB-INF/lib 文件夹下面。之所以要把该 JAR 文件放在 JavaBridge Web 应用程序的类路径(lib 目录)下,是因为 JavaBridge Web 应用程序实际负责实例化 JAR 包中的 Java 类。MessageHelper 类的这一方法与 Web Server 是在同一个虚拟机中执行的——在本例中,就是执行 Jetty 实例和 ActiveMQ 的那个虚拟机。

PHP 示 **** 例

下面的 PHP 脚本使用了 Java.inc 文件,它是 PHP/Java 桥自带的文件。然后 PHP 脚本创建 Java 对象并调用其方法:

复制代码
<?php
require_once ("java/Java.inc");
java_autoload('messageHelper.jar');
$helper = java('com.example.bridge.MessageHelper');
$url = 'tcp://localhost:61616';
$subject = '/topic/MyTopic/';
$message = 'Hello, world!!';
$helper->sendMessage($url, $subject, $message);
echo "Message sent";
?>

在 PHP 脚本中,java_autoload() 方法加载 JAR 文件。java() 方法使用 Java 对象全名来载入 Java 对象。 Java 对象加载后,PHP 脚本通过为 Java/PHP 桥配置的端点调用 SendMessage() 方法。

为 Java/PHP 桥配置端点需要在 java 目录的 java.inc 文件中进行配置。通过改变端点,您可以在不同的 Web 服务器中执行 PHP 脚本。如果您已经有一个配置了 PHP 的 Web 服务器,您可以把该校本放在一个 Web Document 目录下并执行它。要让您的 PHP 脚本运行正常,您还必须将发布包中的 java 目录放在与 PHP 脚本相同的目录下(查看 PHP/Java Bridge 以了解详情)。

在上例中,桥接只建于 PHP 和 Java 之间,使得 PHP 代码可以调用 Java 对象。而例子中不需要从 Java 到 PHP 的桥接。

实战例子:用BlazeDS发送和接收消息

要看实战的例子,先要启动 Flex 应用程序。在另一个浏览器中,运行连接到 PHP/Java 桥的 PHP 脚本。您会在 Flex 用户界面上看到“Hello, world”消息。

使用STOMP协议与PHP集成

STOMP 是另一种技术,您可以用它来弥合 PHP 和 ActiveMQ JMS 之间的鸿沟。在这个例子中,ActiveMQ 使用 STOMP 协议从 PHP 脚本接收消息,然后把消息路由到 JMS Topic,Flex 应用程序接收消息并在界面上显示消息。

STOMP**** 概述

STOMP 是一个协议,它可以使用多种不同的客户端发送消息。尽管 ActiveMQ 已内建了对 STOMP 的支持,你还是可以使用类似 StompConnect 这样的 STOMP 类库与 JMS 通信。

下面的例子说明了如何在 ActiveMQ 中使用内建的 STOMP 协议支持。与 STOMP 一起工作的消息代理(message broker)需要在 conf/activemq.xml 配置文件中打开:

复制代码
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616" />
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613" />
</transportConnectors>

添加了 STOMP 代理的配置后,重启 ActiveMQ。当 ActiveMQ 启动时,它会把“STOMP 连接器已经启动”的消息写入日志文件:

INFO | Connector openwire Started

INFO | Listening for connections at: stomp://silverstreak.local:61613

从 PHP 脚本经由 STOMP 发送的消息被 ActiveMQ 接收,接收到的消息被放入 JMS 主题或 JMS 队列,由相同的消费者接收。经由 STOMP 发送消息还使得 Flex 界面无需修改代码或配置就能接收同样的消息。在这种方式下,利用 STOMP 将消息发送到 ActiveMQ,对应用程序的其它部分来说,是相当透明的。

PHP**** 代码

您可以使用下面的 PHP 脚本利用 STOMP 来把消息发送到与前面例子相同的 MyTopic JMS 主题(本文一直在使用)。代码使用的 Stomp.php 类来自于 FuseSource 。Stomp.php 类提供了一个从 PHP 发送消息的简单方法。要使用这个类,你必须下载该发布包并将其文件复制到示例脚本相同的目录中:

复制代码
try {
// include a library
require_once("Stomp.php");
// make a connection
$con = new Stomp("tcp://localhost:61613");
// connect
$con->connect();
// send a message to the queue
$con->send("/topic/MyTopic", "Hello, world");
echo "Sent message with body 'test'\n";
$con->disconnect();
} catch (Exception $e) {
var_dump($e->getMessage());
}
?>

此代码连接到 ActiveMQ 服务器的 61613 端口,并发送一个很短的文本消息(“Hello, world”)。然后,它从 STOMP 连接器断开连接。

ActiveMQ 把消息路由到相应的 JMS 主题。Flex 应用程序能够接收到这个消息,因为 Flex 订阅了此主题。

实战例子

要看到实战的例子,请再次打开 Flex 应用程序。另外打开一个浏览器,运行您刚才创建的 PHP 脚本,“Hello, world”消息将会显示到 Flex 应用程序的界面上。

使用 ****JNDI

为简单起见,本系列的所有例子均直接使用了队列名和主题名(比如:/topic/MyTopic)。然而,在使用 JMS 的生产环境中,JMS 主题名或队列名一般是使用 JNDI(Java Naming and Directory Interface)进行配置的,而不会采用硬编码的方式。

JNDI 是一个 Java 标准,它允许你抽象 JMS 队列名、主题名、甚至是主机名的实际名称。JNDI 有点像域名系统(DNS),使您能够使用主机名而不是 IP 地址来识别主机。使用 JNDI 可以让您随时调整服务器上的 JMS 主题或队列的位置和实现,而不必修改您的代码。

除了抽象主题名和队列名之外,JNDI 还提供了另一个有用的功能:能够使用 Java EE 的 JMS 对象接口来编写代码。使用接口而不是具体的实现,可以使您的 Java 代码不依赖于特定的供应商。

看看下面的 Java 代码例子:

复制代码
javax.naming.Context ctx = new javax.naming.InitialContext();
javax.jms.ConnectionFactory factory = (javax.jms.ConnectionFactory)ctx.lookup("ConnectionFactory");
javax.jms.Connection conn = factory.createConnection();
javax.jms.Destination destination = (javax.jms.Destination)jndiContext.lookup("MyTopic");
javax.jms.Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
// send the message...
javax.jms.MessageProducer producer = session.createProducer(destination);
javax.jms.TextMessage message = session.createTextMessage();
message.setText("Hello, world!");
producer.send(message);
conn.close();

以上 Java 代码没有使用 ActiveMQConnectionFactory 的具体实现,而是使用了 InitialContext 对象来“查找(lookup)”指定的连接器工厂实现。然后,代码使用 InitialContext 对象上相同的查询方法(lookup)来获取 JMS 主题的引用。这样,本例的代码中就不会包含对 ActiveMQ 的直接引用。

使用 JNDI 的缺点——除了要学习如何在 Java 代码中使用 JNDI 之外,还需要提供一些额外的配置,以获取初始的 JDNI 上下文。对于前者,ActiveMQ 提供了一个简单的 JNDI InitialContextFactory 以方便使用。(请参阅 ActiveMQ 支持页面以获取更多信息)。至于需要额外的配置,无需修改代码即可在不同厂商提供的应用服务器上部署和执行这一优点可以抵消掉这一瑕疵。如果您的环境有可能切换到不同的供应商,您可以考虑使用 JNDI 来帮助抽象细节。

网络考虑因素

此集成解决方案提供了 PHP 和 Flex 客户端通过 Java/JMS 技术在网络上进行通信的功能。因为您可以把不同的内容部署到不同的 Web 服务器,在评估集成技术时还需考虑网络访问的一些因素。

如果在 PHP、Flex 和 Java/JMS 服务之间存在防火墙,防火墙开放的端口可能会影响您选择用于集成的方法。由于 BlazeDS 是通过 MessageBroker Servlet 将 Flex 界面连接到 JMS 的,因此服务器只需标准的 80 端口(或 Web 应用服务器绑定的任何端口)能够访问即可。

ActiveMQ 使用非标准的端口来监听消息,但如果 ActiveMQ 与 BlazeDS 作为 Web 应用服务器运行在同一台机器上时,端口(“openwire”连接器的 61616 端口)问题只受限于本地接口,而不是公开暴露出来。

您的 Web 应用服务器可以在 80 端口暴露 REST Web 服务,使得跨网络和服务器进行集成相对简单。基于这个原因,许多人会选择 Web Services。

PHP/Java 桥使用了部署在 JavaBridge Web 应用程序中的一个 Servlet,通过 XML 流机制暴露 Java 类给 PHP。因为这个桥接是作为一个 Servlet 安装的,所以也可以从 Web 服务器的标准端口访问。

但是,使用 STOMP 协议需要在 PHP 脚本和(ActiveMQ 的)STOMP 消息代理之间开放一个非标准的端口。上面例子中开放的端口是 61613 端口。如果限制了从网络访问这个端口,那么 STOMP 或许并不是集成 PHP 脚本、Flex 界面及 Java/JMS 服务一个好的解决方案。

小结

JMS 是一个消息传递服务,支持主题和队列,其很多特性使其成为稳定消息传递的一个很好选择。BlazeDS 使得您无需付出很多工作量即可让 Flex 应用程序从 Flex 客户端发送消息到 JMS。

本系列的第1 部分介绍了JMS 的消息传递,并示范了如何配置BlazeDS 与JMS 队列进行通信。文章还介绍了使用Java 实现的REST Web 服务来集成PHP 应用程序和JMS 的方法,让您的Flex 用户界面可以从PHP 脚本收到消息。

本文则介绍了从PHP 发送消息到JMS 主题或队列的另外两种方法。PHP/Java Bridge 是一个开源项目,提供了一个从PHP 脚本调用Java 类的框架。通过编写单个的Java 类——即所谓的Fa?ade 模式,您的PHP 脚本就能够将消息发送到JMS,并且从Flex 界面接收到此消息。STOMP 是一个协议,它有多种语言的支持库。利用STOMP,您可以在Flex 应用中与JMS 消息代理通信并接收消息。

总之,这些不同的技术提供了整合PHP、Flex 或Java 应用的不同选项。整合现有的应用程序而不是重新开发它们,可以节省您的时间和精力,而且您也能自由选择适合您需要的最佳实现。

关于作者

Nathan A. Good 居住在 Minnesota 的 Twin 城地区。其专长是软件开发、软件架构和系统管理。平时不编写软件时,他喜欢组装 PC 和服务器、阅读和使用新技术,并鼓励他的朋友转用开源软件。他是许多书籍和文章的作者或合著者,其中包括《Professional Red Hat Enterprise Linux 3》、《Regular Expression Recipes: A Problem-Solution Approach》以及《Foundations of PEAR: Rapid PHP Development》。

查看英文原文: BlazeDS and JMS for PHP Developers, Part 2


译者简介:李强,计算机硕士,毕业于电子科技大学,目前在四川长虹电器股份有限公司技术中心从事研发工作,主要研究领域是 SOA、ESB、Web 服务以及分布式应用等。

感谢宋玮对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2010-07-19 02:403756

评论

发布
暂无评论
发现更多内容

基于STM32+SHT30设计的环境温度与湿度检测系统(IIC模拟时序)

DS小龙哥

9月月更

mac苹果电脑小霸王游戏:FC红白机游戏600合集 for mac 单机游戏下载

你的猪会飞吗

Mac游戏下载 Mac游戏推荐

After Effects 2022 for Mac(AE 2022) v22.6.0中文激活版

Rose

在Mac电脑和Android设备上进行数据传输:Coolmuster Android Assista

理理

纯CSS实现海浪文字效果

南城FE

CSS 前端 动画

苹果电脑cpu温度监测工具 Turbo Boost Switcher Pro for mac 兼容M芯

理理

阿里云Elasticsearch AI搜索实践

阿里云大数据AI技术

人工智能 自然语言处理 elasticsearch rag AI搜索

交互式UI原型设计神器 Principle for Mac 直装激活版

Rose

XMind for mac (XMind思维导图) v24.01中文永久许可 支持M1/M2/M3

Rose

避坑指南!细说Python自动化办公的5大缺点

程序员晚枫

Python 自动化办公

正式开拍!快手联合9大导演使用可灵AI拍摄电影;百度文心一言市场负责人张全文否认放弃通用大模型|AI日报

可信AI进展

Tableau Desktop Pro 2020(数据分析软件)破解版安装包

Rose

Apeaksoft Video Fixer for Mac 视频修复软件

Rose

iZotope RX 10:重塑音频修复与增强新标准,专业音质触手可及

理理

跨平台键鼠共享工具 synergy for mac 中文版 附synergy最新2024永久密钥

理理

Mac版CAD迷你看图软件都可以做什么?CAD迷你看图破解资源分享

理理

阿里巴巴中国站1688商品搜索API返回值深度解析与实战应用

代码忍者

API 测试 API 策略

智进AI,共话增长 | 数智时代,企业需要什么样的AI生产力?

ToB行业头条

看!全是科技与狠活的“统一终端安全”,如何为终端设备叠buff

芯盾时代

身份安全 终端安全 统一运维

VMware Fusion Pro 13 for Mac(VM虚拟机) v13.5.0中文激活版

Rose

mac文件隐藏加密 MacPawHider 2 v2.5.1激活版

Rose

C++ 之 perf+火焰图分析与调试

梦笔生花

perf C++ 火焰图

SyncBird Pro for Mac(iPhone文件管理器) v4.1.1激活版

Rose

【重磅升级】积木报表 v1.8.1 版本发布,支持填报功能

JEECG低代码

【Tomcat源码分析 】 类加载机制的源码解读

派大星

tomcat源码解读

SyncBird Pro for Mac(iPhone文件管理器) v4.1.1激活版

Rose

ON1 Photo RAW MAX 2024.5 功能强大的AI照片编辑软件

理理

国产游戏蓄力,火山引擎ByteHouse助力游戏厂商造爆款

字节跳动数据平台

数据库 大数据 云原生 Clickhouse 数仓

合同管理软件分析:主流的10款哪个好?

爱吃小舅的鱼

系统开发

Nitro PDF Pro for Mac(全能PDF编辑软件) v13.3.1fix激活版

Rose

Moment for Mac(菜单栏倒数日应用) v1.4激活版

Rose

PHP开发者的BlazeDS和JMS指南,第二部分_Java_Nathan A. Good_InfoQ精选文章