java rpc 综述(上)
记得来newland面试的时候,有一个笔试题是关于rmi,rpc cobar web service的选择题。当时对这些不是很懂,除了一个Web Service.
那时候天真的认为要远程调用服务除了Web Service还是Web Service。
最近晚上正好有时候,就介绍下java中几种调用rpc的方式吧。
一、RMI
RMI(remote method Invocation)远程方法调用,从JDK1.1开始就出现,极大的增强了java的分布式处理能力。
相对于其他的rpc,RMI
优势在于无需引入其他外部的jar包,对于处理一些小的应用,会非常的方便和轻巧。
劣势是只能是java-to-java模式,无法使用其他语言来调用。
为了弥补RMI的劣势,后面出现了RMI-IIOP,极大的兼容了COBRA。当然,这不是本篇文章的主题。
那么如何调用RMI呢?这里给出一个简单的例子。
1.创建接口
说明的是这个接口必须继承Remote类,同时远程调用的所有方法都需要抛出RemoteException异常
1 public interface IHello extends Remote{ 2 /** 3 * 远程调用的接口 必须抛出 RemoteException 4 * */ 5 public String say(String msg)throws RemoteException; 6 7 }
2.创建接口实现类
1 public class IHelloImpl extends UnicastRemoteObject implements IHello { 2 3 /** 4 * 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,因此这里默认的构造方法必须写,必须声明抛出RemoteException异常 5 * 6 * @throws RemoteException 7 */ 8 public IHelloImpl() throws RemoteException { 9 super(); 10 // TODO Auto-generated constructor stub 11 } 12 13 public String say(String msg) { 14 // TODO Auto-generated method stub 15 return "远程接口调用:" + msg; 16 } 17 18 }
3.注册开启本地RMI服务
1 public class HelloServer { 2 3 public HelloServer() { 4 } 5 6 public static void main(String[] args) { 7 new HelloServer().start(); 8 } 9 10 private void start() { 11 12 try { 13 IHello hello = new IHelloImpl(); 14 // 创建注册表对象 15 LocateRegistry.createRegistry(10000); 16 // banding远程对象到RIMI注册表上 rmi协议可以缺省 17 Naming.bind("rmi://localhost:10000/RHello", hello); 18 System.out.println("启动远程RMI注册服务"); 19 20 } catch (RemoteException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } catch (MalformedURLException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } catch (AlreadyBoundException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 31 } 32 33 }
4.测试
1 //远程服务如果未开 则抛出Connection refused to host 2 IHello hello=(IHello) Naming.lookup("//localhost:10000/RHello"); 3 System.out.println(hello.say("你好"));
二、XML-RPC
官网地址:http://ws.apache.org/xmlrpc/index.html
XML-RPC(XML-based Remote Procedure Call,基于 XML 的远程过程调用)是一种已http协议,XML格式为载体的RPC。
XML-RPC 具有简单、高效且易于实现等优点,因此她也一直是中小型引用实现分布式的最佳方案之一。
官网对于XML-RPC的有点给出了以下解释(自己翻译)
1.支持所有java的基础类型
2.日历对象也是支持的,特别timezone和milliseconds也是可以进行发送请求的。
3.DOM nodes, or JAXB objects也是允许被传输的。最重要的是实现了java.io.Serializable interface
接口的对象都是允许的,话外之音,开发者自定义的实体对象都是允许的。nice.(*^__^*)
4.服务端和客户端都运行在流模式中,远比默认的模式(基于内部的大数据字节数组)来的好。
更多关于XML-RPC类型 参考这里:http://ws.apache.org/xmlrpc/types.html
理论说完,我们就来编写一个XML-RPC的例子。这里针对的是XML-RPC2.0的库进行开发的3.x就有区别了
首先创建一个java web project。引入xercesImpl-2.9.1.jar,xmlrpc-2.0.jar,xmlrpc-client-3.1.3.jar包
另外还需要引入commons-codec-1.3.jar,否则会提示org/apache/commons/codec/DecoderException
1.创建服务
//xml rpc 服务类 public class MyXmlRpcServer { public byte[] test(int flag) { if (flag==1) return "admin".getBytes(); else return "guest".getBytes(); } }
2.创建一个servlet。
public class XmlRpcServlet extends HttpServlet { private XmlRpcServer rpcServer=new XmlRpcServer(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { byte[] result = rpcServer.execute(request.getInputStream()); response.setContentType("text/xml"); response.setContentLength(result.length); OutputStream out = response.getOutputStream(); out.write(result); out.flush(); out.close(); } public void init() throws ServletException { //定义一个服务名为myServer的xml rpc服务 rpcServer.addHandler("myServer", new MyXmlRpcServer()); rpcServer.setMaxThreads(20); } }
需要说明的是doPost方法中的返回值,是根据MyXmlRpcServer 类的方法进行强转化的,并且ContentType 必须是
text/xml,而不是原先servlet自带的text/html。
<servlet> <servlet-name>XmlRpcServlet</servlet-name> <servlet-class>com.lwx.xmlrpc.servlet.XmlRpcServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>XmlRpcServlet</servlet-name> <url-pattern>/XmlRpcServer</url-pattern> </servlet-mapping>
3.客户端
public class ClientTest { public static void main(String[] args) throws ClassNotFoundException, XmlRpcException, IOException { // 1.加载驱动 XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); XmlRpcClient client = new XmlRpcClient( "http://localhost:10000/XmlRpcTest/XmlRpcServer"); Vector params = new Vector(); params.addElement(1); byte role[] = (byte[]) client.execute("myServer.test", params); System.out.println(new String(role)); }
如果对XML-RPC3.0感兴趣的可以参考
http://chrui.iteye.com/blog/800447
http://blog.sina.com.cn/s/blog_76fbd24d01018z6g.html
自然,需要研究的话 本篇文章可以看看 http://www.ibm.com/developerworks/cn/webservices/1211_zhusy_rpc/index.html#ibm-pcon
关于XML-RPC的完整例子 可以从这里下载http://download.csdn.net/detail/draem0507/5346924
小结:上面我们简单介绍了RMI和XML-RPC2.0,感兴趣的朋友可以研究RMI-IIOP ,COBRA。当然XML-RPC3.0
也看去看下,顺便补充一句.XML-RPC客户端发送的请求有两种方式
第一种就是例子中的,使用的是Java.net.URLConnection。
第二种是org.apache.xmlrpc.XmlRpcClientLite:自身提供轻量级的http client实现
加入我们需要使用http协议(代理,重定向)则必须使用第一种方式,否则的话第二种方式值得考虑。
最重要的是根据平台来决定,有的平台第一种更快,有的则是第二种。
打个广告,java rpc 综述(下) 将重点介绍下基于SAOP的Web Service。有机会会结合android的天气预报的例子来做说明。
另外:求一份福州android的offer。嘎嘎。