flex和blazeds
本系列的第一部分介绍了通过使用BlazeDS将Java服务,PHP和Adobe Flash Builder用户界面(UI)与Java消息服务(JMS)集成。 它展示了如何进行一些配置更改,即可使用BlazeDS通过MessageBroker Servlet将Flash Builder中内置的UI连接到JMS队列。 第1部分还介绍了将PHP与Java和JMS集成的另一种方法:使用代表性状态传输(REST)Web服务将消息放置在JMS队列上。
本系列的第2部分讨论如何将PHP和Java与其他两种方法集成。 第一种方法(桥接)使您可以使用PHP中的Java对象,从而公开了另一种方法,即通过Java通过PHP在JMS队列上放置消息。 集成的第二种方法是使用流文本定向消息传递协议(STOMP),这是可用于与JMS的ActiveMQ实现通信的另一种协议。 ActiveMQ收到消息后,将其放置在JMS队列中,并且Adobe Flex应用程序接收到该消息。
通过桥接与Php集成
本系列的第1部分演示了如何使用BlazeDS和JMS将消息从Java发送到Flex并返回。 其他技术也使PHP-Java集成成为可能,从而允许您将消息间接地放在JMS队列上。 Java / PHP Bridge是这些技术之一。 它允许您使用已经配置并在ActiveMQ中工作的JMS队列。 使用Java / PHP桥,您可以编写一个PHP脚本来调用Java类中的方法。 该方法将JMS消息放在队列中。 Flex用户界面使用BlazeDS连接到JMS队列,然后像使用REST Web服务一样在队列上接收消息。
PHP / Java Bridge发行版带有JavaBridge.war文件。 将此Web存档(WAR)文件解压缩到ActiveMQ的webapps / JavaBridge目录中,然后将应用程序添加到conf / jetty.xml文件中。 JavaBridge Web应用程序包含Servlet,这些Servlet从PHP脚本接收消息,对其进行解码并运行Java类。
Java示例
因为PHP脚本和Java类之间的通信速度很慢,所以创建一个Java类可以用一种方法处理工作。 这样做称为外观,在这种模式下,您可以在公开的简单方法后面隐藏更复杂的功能。
这是Java示例外观类,称为MessageHelper:package 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,所用主题的名称以及消息。
将完成的类放入Java存档(JAR)文件中,然后将JAR放在JavaBridge Web应用程序文件夹(webapps / JavaBridge)的WEB-INF / lib文件夹中。 将JAR放入JavaBridge Web应用程序的类路径(lib文件夹)中,因为JavaBridge Web应用程序实际上是在实例化Java类。 MessageHelper上的方法在与Web服务器相同的虚拟机(VM)中执行-在这种情况下,是ActiveMQ随附的Jetty实例。
PHP示例
这里PHP脚本使用PHP / Java Bridge随附的Java.inc文件。 然后,它创建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";
?>
java_autoload()方法在PHP脚本中加载JAR。 java()方法使用完全限定的Java对象名称加载Java对象。 加载Java对象后,PHP脚本通过Java / PHP桥的已配置端点调用sendMessage()方法。
Java / PHP桥的端点是在java文件夹中的Java.inc文件中配置的。 更改端点可以使您在其他Web服务器中执行PHP脚本。 如果您已经具有配置了PHP的Web服务器,则可以将此脚本放置在该服务器的Web文档文件夹中并执行它。 为了使PHP脚本正确运行,还必须在发行版的脚本所在的文件夹中包含该发行版附带的java文件夹(有关详细信息,请参见PHP / Java Bridge)。
在此示例中,仅在PHP和Java之间建立了桥梁,从而允许PHP代码调用Java对象。 对于此示例,从Java到PHP的桥接是不必要的。
实际示例:使用BlazeDS进行接收和发送
要查看实际的示例,请启动Flex应用程序。 在其他浏览器中,运行连接到PHP / Java BridgePHP脚本。 您将在Flex UI中看到消息“ Hello,world”。
通过Stomp与Php集成
STOMP是另一种可用于弥合PHP与ActiveMQ JMS实现之间的差距的技术。 在此示例中,ActiveMQ JMS实现通过STOMP从PHP脚本接收消息,然后ActiveMQ将消息路由到Flex UI正在使用的JMS主题。
STOMP概述
STOMP是用于使用许多不同客户端发送消息的协议。 尽管ActiveMQ内置了对STOMP的支持,但是您也可以使用STOMP通过诸如StompConnect之类的库与JMS通信。
此处的示例演示了如何在ActiveMQ中使用对STOMP的内置支持。 首先需要在conf / activemq.xml文件中打开与STOMP一起使用的消息代理:
<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”连接器已启动:
信息| 连接器openwire已启动
信息| 在以下位置收听连接:stomp://silverstreak.local:61613
通过STOMP从PHP脚本发送的消息由ActiveMQ接收,放在JMS主题或队列上,并由相同的使用者接收。 通过STOMP发送消息仍然允许Flex接口接收相同的消息,而无需更改Flex代码或配置。 以这种方式,使用STOMP将消息发送到ActiveMQ对应用程序的其余部分是相当透明的。
PHP代码
您可以使用以下PHP脚本将使用STOMP的示例消息发送到本文中使用的同一MyTopic JMS主题。 此代码使用FuseSource中的Stomp.php类。 Stomp.php类提供了一种从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());
}
?>
该代码在端口61613上附加到ActiveMQ服务器,并发送一条短文本消息(“ Hello,world”)。 然后,它与STOMP连接器断开连接。
ActiveMQ将消息路由到适当的主题。 Flex应用程序将能够接收到该消息,因为它已订阅了该主题。
实际例子
要查看实际操作中的示例,请再次打开Flex应用程序。 打开另一个浏览器,并使用它运行您创建PHP脚本。 “ Hello,world”消息将出现在Flex应用程序中。
使用JNDI
本系列中的所有示例都直接使用了队列和主题的名称(例如,/ topic / MyTopic),以使其简单。 但是,在使用JMS的生产系统中,可以使用Java命名和目录接口(JNDI)而不是硬编码的值来配置主题或队列的名称。
JNDI是一种Java标准,允许您抽象JMS队列,主题甚至主机名的实际名称。 JNDI非常类似于使用域名系统(DNS)启用主机名而不是IP地址来标识主机。 使用JNDI,您可以更改主题或队列在服务器上的位置和实现,而不必更新任何代码。
除了抽象主题和队列的名称之外,JNDI还提供了另一个有用的功能:使用JMS对象的Java平台企业版(Java EE)接口编写Java代码的功能。 使用接口而不是具体的实现方式可以减少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对象“查找”了特定的连接工厂实现。 然后,代码使用InitialContext对象上的相同查找方法获取对JMS主题的引用。 结果是该示例代码不直接包含对ActiveMQ的引用。
除了学习如何在Java代码中使用JNDI之外,使用JNDI的一个缺点是需要提供一些其他配置来获取初始JDNI上下文。 ActiveMQ为此提供了一个简单的JNDI InitialContextFactory。 (有关更多信息,请参见ActiveMQ支持页面 。) 无需配置其他供应商就可以部署和执行Java代码而无需修改应用服务器的优势,可以抵消附加配置的缺点。 如果您的环境中有可能更换供应商,则可以考虑使用JNDI来帮助抽象细节。
网络注意事项
集成解决方案使PHP和Flex客户端能够通过网络与Java / JMS技术进行通信。 因为您可以将不同的部分部署到不同的Web服务器,所以在评估集成技术时必须考虑网络访问。
如果PHP,Flex和Java / JMS服务之间存在防火墙,则允许的端口可能会影响您决定使用哪种集成方法。 因为BlazeDS通过MessageBroker servlet将Flex UI链接到JMS,所以仅需要从Flex UI访问服务器上的标准端口80(或Web应用程序服务器绑定的任何端口)。
ActiveMQ在侦听消息传递时使用非标准端口,但是如果ActiveMQ与执行BlazeDS的Web应用程序服务器在同一台物理计算机上运行,则该端口(“ openwire”连接器的端口为61616)可能仅限于本地主机接口,并且不会公开公开。
您的Web应用程序服务器可以在端口80上公开REST Web服务,从而使它们成为跨网络和服务器进行集成的相对简单的方法。 因此,许多人选择Web服务。
PHP / Java Bridge使用部署在Web应用程序服务器上JavaBridge Web应用程序中的servlet,通过其可扩展标记语言(XML)流机制将Java类公开给PHP。 由于网桥是作为Servlet安装的,因此也可以从Web服务器的标准端口中使用它。
但是,使用STOMP要求在PHP脚本和STOMP消息代理(ActiveMQ)之间打开非标准端口。 这些示例中的端口是61613。如果对该端口的网络访问受到限制,则STOMP可能不是将PHP脚本与Flex UI和Java / JMS服务集成的理想解决方案。
摘要
JMS是一种支持主题和队列的消息传递服务,它具有许多功能,使其成为健壮消息传递的理想选择。 BlazeDS允许您的Flex应用程序轻松地将消息从Flex客户端发送到JMS实现。
本系列的第1部分介绍了JMS消息传递,并演示了如何配置BlazeDS与JMS队列进行通信。 它还介绍了一种使用Java中实现的REST服务将PHP应用程序与JMS集成的方法,从而使Flex UI可以从PHP脚本接收消息。
本文介绍了使用另外两种从PHP向JMS主题或队列发送消息的方法。 PHP / Java Bridge是一个开源项目,它提供了一个框架,用于从PHP脚本调用Java类。 通过编写一个称为外观的 Java类,您可以为您PHP脚本提供将消息发送到JMS的功能,以供您的Flex UI接收。 STOMP是一种协议,带有以多种语言实现的支持库。 使用STOMP,您可以与JMS消息代理进行通信并在Flex应用程序中接收消息。
这些不同的技术在一起提供了用于集成以PHP,Flex或Java实施的应用程序的不同选项。 集成现有应用程序而不用重写它们可以节省您的时间和精力,并且集成功能使您可以自由选择适合您需求的最佳实现。
flex和blazeds