论坛首页 Java企业应用论坛

java服务端flex客户端PHPRPC的简单入门示例以及mxml创建PHPRPC_Client对象的讨论

浏览 3491 次
该帖已经被评为隐藏帖
作者 正文
   发表时间:2009-07-14   最后修改:2009-07-14
声明:这是一篇入门级的文章,主要目的是介绍java服务器端以及flex客户端使用PHPRPC快速上手的小例子。欢迎大家多提意见,有不足之处很欢迎大家提出来。本人也是新手,常看贴少发帖,所以as代码不知道如何处理,按照java代码的格式发表了,不知是否妥当,希望各位看帖的朋友不要被误导以为是java代码,文中as代码均已经说明。

在javaEye上看到了一种十分吸引人的RPC技术――PHPRPC。PHPRPC 是一个轻型的、安全的、跨网际的、跨语言的、跨平台的、跨环境的、跨域的、支持复杂对象传输的、支持引用参数传递的、支持内容输出重定向的、支持分级错误处理的、支持会话的、面向服务的高性能远程过程调用协议。经过简单的试用,我的感觉总体上说,PHPRPC是一种使用相当简便易用的远程过程调用协议。经过测试(论坛上有人编写了详尽的测试程序对比多种RPC协议的执行效率)PHPRPC有着优于现在主流RPC协议框架的序列化和反序列化的效率。使用PHPRPC可以轻松的实现现在主流的web service框架经过复杂的配置和编码才能实现功能(很多甚至需要用工具声称接口描述文件(IDL或者WSDL)),开发出稳定高效的分布式应用。是SOA的理想解决方案。
PHPRPC对多种主流编程语言都提供了服务端和客户端组件(是我所见过的RPC协议框架中支持语言最多的,并且还在陆续增加中,当然像AS这种侧重前端开发的语言只提供了客户端组件)。我选择了最熟悉的java和as的组件来体验了一下。写了一个小例子,大体上是这样的,用java servlet通过PHPRPC的服务器端发布服务,然后通过java客户端和flex客户端调用服务器发布的服务。并且通过对PHPRPC for AS3客户端做一点点修改,实现使用mxml标签访问服务器端发布的服务的flex自定义标签。

代码如下
Java servlet:
package org.frey.psft;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.phprpc.PHPRPC_Server;

import org.phprpc.PHPRPC_Server;

public class ComputeServlet extends HttpServlet {	
	public void doGet(HttpServletRequest request, HttpServletResponse response)   
    throws ServletException, IOException 
    {   
   		 this.doPost(request, response);   
    }   
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException   	{
		PHPRPC_Server ps=new PHPRPC_Server();
		ps.add("SayHi",SaySomething.class);	
		ps.add("SayGoodbye",SaySomething.class);	
		ps.start(request, response);
	} 
}



这个servlet和很一般,只不过在dopost()方法中使用PHPRPC的server API把一个类提供的方法作为服务发布出来了。
提供发布为服务的方法的类:

package org.frey.psft;
import java.io.PrintWriter;
public class SaySomething {	
	public static String SayHi(String to)	{
		System.out.println("Hi,"+to);
		return "Hi,"+to;
	}
	
	public static String SayGoodbye(String to)	{
		System.out.println("SayGoodbye,"+to);
		return "Goodbye,"+to;
	}
}


这个类更是没有什么要求,一般的POJO就可以,如果作为类发布服务,则可发布的方法为类中的静态方法。当然也可以吧对象的方法发布为服务供远程客户端访问,方法也类似,都十分简单,官方文档讲得十分清楚。这里由于只是一个小例子,就采用最简单的类发布静态方法为服务的方式了。
然后可以吧这个web工程部署在tomcat等服务器下,web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>PhprpcServletFlexTest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
		<servlet-name>psft</servlet-name>
		<servlet-class>org.frey.psft.ComputeServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
		<servlet-name>psft</servlet-name>
		<url-pattern>/psft.do</url-pattern>
	</servlet-mapping>
  
</web-app>


部署后请确保phprpc.jar放到web-inf/lib目录下,此jar文件的生成依赖于不同服务器提供的servlet包,tomcat的是servlet-api.jar,把此文件放到下载来的phprpc_3.0.2_java\java下运行make.bat就可以生成。同时生成的phprpc_client.jar是java客户端调用服务的时候需要的API的包,在编写java客户端的时候需要用到。


Java客户端

import org.phprpc.*;   
import java.io.*;     
interface IUpload {   
	public String SayHi(String to,PrintWriter out);	
	public String SayGoodbye(String to,PrintWriter out);	
}     
public class UploadClient {   
    public static void main(String[] args) throws IOException {   
        //if (args.length > 0) {   
            PHPRPC_Client client = new PHPRPC_Client("http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do");   
            //client.setProxy("10.1.0.1", 8000);   
            //client.setKeyLength(512);   
            //client.setEncryptMode(1);   
            //String filename = args[0];   
            IUpload upload = (IUpload)client.useService(IUpload.class);   
            String hi=upload.SayHi("frey", null);
            String gb=upload.SayGoodbye("frey", null);
            System.out.print(hi);
            System.out.print(gb);
        //}   
    }   
}  



客户端包含一个接口和一个服务调用的类。接口需要声明和远程服务提供者类发布的相同的方法,这种情况使用过RMI或者Corba的应该觉得再正常不过了。但PHPRPC最强大的地方就是他发布和访问服务的过程都及其简单,符合用户的使用习惯,你可以像使用本地方法一样使用远程方法。注意IP地址换成服务端所在的机器的IP,如果都在本机的话可以就用localhost。如果服务器是tomcat默认端口是8080。
运行这个客户端就可以看到调用远程方法的结果。这就是一个java服务器端和客户端的简单例子。

前面说到PHPRPC提供多语言的组件,我选择了比较熟悉的AS3客户端组件来写一个flex客户端访问远程方法的小例子。
先看代码:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:phprpc="org.phprpc.*" xmlns:local="*">

	<mx:Script>
	<![CDATA[
	
	import org.phprpc.PHPRPC_Client;
	import org.phprpc.PHPRPC_Error;
	import mx.controls.Alert;
	import flash.utils.ByteArray;
        	
            [Bindable]
            //public var pc:PHPRPC_Client=new PHPRPC_Client('http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do',['SayHi','SayGoodbye']); //通过PHPRPC_Client构造函数初始化PHPRPC_Client对象,并在此处规定要访问的方法
            //public var pc:PHPRPC_Client=new PHPRPC_Client('http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do'); //也可以不指定特定的访问方法
            
            public function shcallback(result:ByteArray,args:Array,output:String,warning:PHPRPC_Error)
            {
            	ta.text=result.toString();
            	trace("sayHi");
            }       //可以吧回调函数单独定义     
            public function sgcallback(result:ByteArray,args:Array,output:String,warning:PHPRPC_Error)
            {
            	ta.text=result.toString();
            	trace("sayGoodbye");
            }            
            public function sayHi():void
            {                        	
            	//pc.SayHi(ti.text,null,function (result:ByteArray,args:Array,output:String,warning:PHPRPC_Error){ta.text=result.toString();trace("sayHi");});//也可以在动态访问远程方法的参数列表中定义回调函数
            	mpc.SayHi(ti.text,null,shcallback);            	
            }    //这里mpc是通过mxml标签形式创建的PHPRPC_Client对象
            
            public function sayGoodbye():void
            {                    
            	 //pc.SayGoodbye(ti.text,null,function (result:*,args:Array,output:String,warning:PHPRPC_Error){ta.text=result.toString();trace("sayGoodbye");});
            	mpc.SayGoodbye(ti.text,null,sgcallback);
                        }
                        
              ]]>
    </mx:Script> 

	<mx:Panel x="10" y="10" width="543" height="310" layout="absolute" title="psftClient">
		<mx:TextInput id="ti" x="120" y="10"/>
		<mx:Label x="10" y="12" text="input your name:"/>
		<mx:Button x="317" y="10" label="say Hi" click="sayHi()"/>
		<mx:Button x="414" y="10" label="say Goodbye" click="sayGoodbye()"/>
		<mx:TextArea id="ta" x="10" y="40" width="503" height="220"/>
	</mx:Panel>
	<local:myPhprpcClient id="mpc" ServerUrl="http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do"/>
	
</mx:Application>



这里创建PHPRPC_Client对象的方式大致有两种,通过PHPRPC_Client构造函数和mxml标签。如果选择mxml标签方式创建此对象,则需要自己稍微修改一下PHPRPC_Client这个as类,因为创建此对象需要serverUrl这个属性,而在PHPRPC_Client类中这个属性没有定义set和get方法,所以不能在标签中作为属性为这些属性给出值。我采用的方法是自己定义了一个类名叫myPhprpcClient,内容和PHPRPC_Client基本一样,但需要在myPhprpcClient这个类的源代码中加入下面的as代码:
public function set ServerUrl(value:String):void {
			setServerUrl(value);
		}		
		public function setServerUrl(value:String):void	{
			m_serverURL=value;
		}
		
		public function get ServerUrl():String {
			return m_serverURL;
		}
		public function getServerUrl():String {
			return m_serverURL;
		}		
		
		public function set Functions(value:Object):void {
			setFunctions(value);
		}		
		public function setFunctions(value:String):void {
			m_functions=value;
		}
		public function get Functions():String {
			return m_functions;
		}
		public function getFunctions():String {
			return m_functions;
		}



主要就是一些set和get函数,目的是在mxml标签中可以为一些属性指定值。这样就可以想例子中那样使用标签创建PHPRPC_Client对象并用标签属性的方式指定服务器的url以及需要调用的方法、加密模式等等一系列属性了。注意给出需要调用的远程方法列表的时候一定要用Object的类型,可以先定义好这么一个对象,然后赋值给Functions这个属性。
我是在论坛上看到有人反映PHPRPC没有mxml的语言支持,所以萌生了自定义标签方式创建PHPRPC_Client的想法。但实现之后,我觉得这样做实在意义不大,通过as的API来创建PHPRPC_Client的语法已经非常简单了,一个设计好的as类完全可以作为标签来使用(原来的PHPRPC_Client.as类只是有些关键属性没有提供set和get方法,所以不能直接作为标签使用)。
一个简单的小例子,希望对于新手有帮助吧。
PHPRPC真的是一个很好的RPC协议,我一看到就被深深的吸引了。希望PHPRPC能得到更多的关注,成为企业级应用所信赖的解决方案。







   发表时间:2009-07-16  
alvase 写道
声明:这是一篇入门级的文章,主要目的是介绍java服务器端以及flex客户端使用PHPRPC快速上手的小例子。欢迎大家多提意见,有不足之处很欢迎大家提出来。本人也是新手,常看贴少发帖,所以as代码不知道如何处理,按照java代码的格式发表了,不知是否妥当,希望各位看帖的朋友不要被误导以为是java代码,文中as代码均已经说明。

在javaEye上看到了一种十分吸引人的RPC技术――PHPRPC。PHPRPC 是一个轻型的、安全的、跨网际的、跨语言的、跨平台的、跨环境的、跨域的、支持复杂对象传输的、支持引用参数传递的、支持内容输出重定向的、支持分级错误处理的、支持会话的、面向服务的高性能远程过程调用协议。经过简单的试用,我的感觉总体上说,PHPRPC是一种使用相当简便易用的远程过程调用协议。经过测试(论坛上有人编写了详尽的测试程序对比多种RPC协议的执行效率)PHPRPC有着优于现在主流RPC协议框架的序列化和反序列化的效率。使用PHPRPC可以轻松的实现现在主流的web service框架经过复杂的配置和编码才能实现功能(很多甚至需要用工具声称接口描述文件(IDL或者WSDL)),开发出稳定高效的分布式应用。是SOA的理想解决方案。
PHPRPC对多种主流编程语言都提供了服务端和客户端组件(是我所见过的RPC协议框架中支持语言最多的,并且还在陆续增加中,当然像AS这种侧重前端开发的语言只提供了客户端组件)。我选择了最熟悉的java和as的组件来体验了一下。写了一个小例子,大体上是这样的,用java servlet通过PHPRPC的服务器端发布服务,然后通过java客户端和flex客户端调用服务器发布的服务。并且通过对PHPRPC for AS3客户端做一点点修改,实现使用mxml标签访问服务器端发布的服务的flex自定义标签。

代码如下
Java servlet:
package org.frey.psft;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.phprpc.PHPRPC_Server;

import org.phprpc.PHPRPC_Server;

public class ComputeServlet extends HttpServlet {	
	public void doGet(HttpServletRequest request, HttpServletResponse response)   
    throws ServletException, IOException 
    {   
   		 this.doPost(request, response);   
    }   
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException   	{
		PHPRPC_Server ps=new PHPRPC_Server();
		ps.add("SayHi",SaySomething.class);	
		ps.add("SayGoodbye",SaySomething.class);	
		ps.start(request, response);
	} 
}



这个servlet和很一般,只不过在dopost()方法中使用PHPRPC的server API把一个类提供的方法作为服务发布出来了。
提供发布为服务的方法的类:

package org.frey.psft;
import java.io.PrintWriter;
public class SaySomething {	
	public static String SayHi(String to)	{
		System.out.println("Hi,"+to);
		return "Hi,"+to;
	}
	
	public static String SayGoodbye(String to)	{
		System.out.println("SayGoodbye,"+to);
		return "Goodbye,"+to;
	}
}


这个类更是没有什么要求,一般的POJO就可以,如果作为类发布服务,则可发布的方法为类中的静态方法。当然也可以吧对象的方法发布为服务供远程客户端访问,方法也类似,都十分简单,官方文档讲得十分清楚。这里由于只是一个小例子,就采用最简单的类发布静态方法为服务的方式了。
然后可以吧这个web工程部署在tomcat等服务器下,web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>PhprpcServletFlexTest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
		<servlet-name>psft</servlet-name>
		<servlet-class>org.frey.psft.ComputeServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
		<servlet-name>psft</servlet-name>
		<url-pattern>/psft.do</url-pattern>
	</servlet-mapping>
  
</web-app>


部署后请确保phprpc.jar放到web-inf/lib目录下,此jar文件的生成依赖于不同服务器提供的servlet包,tomcat的是servlet-api.jar,把此文件放到下载来的phprpc_3.0.2_java\java下运行make.bat就可以生成。同时生成的phprpc_client.jar是java客户端调用服务的时候需要的API的包,在编写java客户端的时候需要用到。


Java客户端

import org.phprpc.*;   
import java.io.*;     
interface IUpload {   
	public String SayHi(String to,PrintWriter out);	
	public String SayGoodbye(String to,PrintWriter out);	
}     
public class UploadClient {   
    public static void main(String[] args) throws IOException {   
        //if (args.length > 0) {   
            PHPRPC_Client client = new PHPRPC_Client("http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do");   
            //client.setProxy("10.1.0.1", 8000);   
            //client.setKeyLength(512);   
            //client.setEncryptMode(1);   
            //String filename = args[0];   
            IUpload upload = (IUpload)client.useService(IUpload.class);   
            String hi=upload.SayHi("frey", null);
            String gb=upload.SayGoodbye("frey", null);
            System.out.print(hi);
            System.out.print(gb);
        //}   
    }   
}  



客户端包含一个接口和一个服务调用的类。接口需要声明和远程服务提供者类发布的相同的方法,这种情况使用过RMI或者Corba的应该觉得再正常不过了。但PHPRPC最强大的地方就是他发布和访问服务的过程都及其简单,符合用户的使用习惯,你可以像使用本地方法一样使用远程方法。注意IP地址换成服务端所在的机器的IP,如果都在本机的话可以就用localhost。如果服务器是tomcat默认端口是8080。
运行这个客户端就可以看到调用远程方法的结果。这就是一个java服务器端和客户端的简单例子。

前面说到PHPRPC提供多语言的组件,我选择了比较熟悉的AS3客户端组件来写一个flex客户端访问远程方法的小例子。
先看代码:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:phprpc="org.phprpc.*" xmlns:local="*">

	<mx:Script>
	<![CDATA[
	
	import org.phprpc.PHPRPC_Client;
	import org.phprpc.PHPRPC_Error;
	import mx.controls.Alert;
	import flash.utils.ByteArray;
        	
            [Bindable]
            //public var pc:PHPRPC_Client=new PHPRPC_Client('http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do',['SayHi','SayGoodbye']); //通过PHPRPC_Client构造函数初始化PHPRPC_Client对象,并在此处规定要访问的方法
            //public var pc:PHPRPC_Client=new PHPRPC_Client('http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do'); //也可以不指定特定的访问方法
            
            public function shcallback(result:ByteArray,args:Array,output:String,warning:PHPRPC_Error)
            {
            	ta.text=result.toString();
            	trace("sayHi");
            }       //可以吧回调函数单独定义     
            public function sgcallback(result:ByteArray,args:Array,output:String,warning:PHPRPC_Error)
            {
            	ta.text=result.toString();
            	trace("sayGoodbye");
            }            
            public function sayHi():void
            {                        	
            	//pc.SayHi(ti.text,null,function (result:ByteArray,args:Array,output:String,warning:PHPRPC_Error){ta.text=result.toString();trace("sayHi");});//也可以在动态访问远程方法的参数列表中定义回调函数
            	mpc.SayHi(ti.text,null,shcallback);            	
            }    //这里mpc是通过mxml标签形式创建的PHPRPC_Client对象
            
            public function sayGoodbye():void
            {                    
            	 //pc.SayGoodbye(ti.text,null,function (result:*,args:Array,output:String,warning:PHPRPC_Error){ta.text=result.toString();trace("sayGoodbye");});
            	mpc.SayGoodbye(ti.text,null,sgcallback);
                        }
                        
              ]]>
    </mx:Script> 

	<mx:Panel x="10" y="10" width="543" height="310" layout="absolute" title="psftClient">
		<mx:TextInput id="ti" x="120" y="10"/>
		<mx:Label x="10" y="12" text="input your name:"/>
		<mx:Button x="317" y="10" label="say Hi" click="sayHi()"/>
		<mx:Button x="414" y="10" label="say Goodbye" click="sayGoodbye()"/>
		<mx:TextArea id="ta" x="10" y="40" width="503" height="220"/>
	</mx:Panel>
	<local:myPhprpcClient id="mpc" ServerUrl="http://9.123.143.55:8080/PhprpcServletFlexTest/psft.do"/>
	
</mx:Application>



这里创建PHPRPC_Client对象的方式大致有两种,通过PHPRPC_Client构造函数和mxml标签。如果选择mxml标签方式创建此对象,则需要自己稍微修改一下PHPRPC_Client这个as类,因为创建此对象需要serverUrl这个属性,而在PHPRPC_Client类中这个属性没有定义set和get方法,所以不能在标签中作为属性为这些属性给出值。我采用的方法是自己定义了一个类名叫myPhprpcClient,内容和PHPRPC_Client基本一样,但需要在myPhprpcClient这个类的源代码中加入下面的as代码:
public function set ServerUrl(value:String):void {
			setServerUrl(value);
		}		
		public function setServerUrl(value:String):void	{
			m_serverURL=value;
		}
		
		public function get ServerUrl():String {
			return m_serverURL;
		}
		public function getServerUrl():String {
			return m_serverURL;
		}		
		
		public function set Functions(value:Object):void {
			setFunctions(value);
		}		
		public function setFunctions(value:String):void {
			m_functions=value;
		}
		public function get Functions():String {
			return m_functions;
		}
		public function getFunctions():String {
			return m_functions;
		}



主要就是一些set和get函数,目的是在mxml标签中可以为一些属性指定值。这样就可以想例子中那样使用标签创建PHPRPC_Client对象并用标签属性的方式指定服务器的url以及需要调用的方法、加密模式等等一系列属性了。注意给出需要调用的远程方法列表的时候一定要用Object的类型,可以先定义好这么一个对象,然后赋值给Functions这个属性。
我是在论坛上看到有人反映PHPRPC没有mxml的语言支持,所以萌生了自定义标签方式创建PHPRPC_Client的想法。但实现之后,我觉得这样做实在意义不大,通过as的API来创建PHPRPC_Client的语法已经非常简单了,一个设计好的as类完全可以作为标签来使用(原来的PHPRPC_Client.as类只是有些关键属性没有提供set和get方法,所以不能直接作为标签使用)。
一个简单的小例子,希望对于新手有帮助吧。
PHPRPC真的是一个很好的RPC协议,我一看到就被深深的吸引了。希望PHPRPC能得到更多的关注,成为企业级应用所信赖的解决方案。








0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics