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。嘎嘎。

 

 

 

 

 

 

 

 

posted @ 2013-05-08 22:00  draem0507  阅读(2487)  评论(1编辑  收藏  举报
View Code