本系列的第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: \u0026lt;\" + url + \"\u0026gt;\");\ System.out.println(\"Using Subject: \u0026lt;\" + subject + \"\u0026gt;\");\ System.out.println(\"Sending Message Text: \u0026lt;\" + messageText + \"\u0026gt;\");\ \ 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对象并调用其方法:
\\\u0026lt;?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-\u0026gt;sendMessage($url, $subject, $message);\\echo \"Message sent\";\?\u0026gt;\\
在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配置文件中打开:
\\\u0026lt;transportConnectors\u0026gt;\ \u0026lt;transportConnector name=\"openwire\" uri=\"tcp://0.0.0.0:61616\" /\u0026gt;\ \u0026lt;transportConnector name=\"stomp\" uri=\"stomp://0.0.0.0:61613\" /\u0026gt;\\u0026lt;/transportConnectors\u0026gt;\\
添加了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-\u0026gt;connect();\ // send a message to the queue\ $con-\u0026gt;send(\"/topic/MyTopic\