java原生的RMI与spring的RMI

 RMI应用程序通常包括两个独立的程序:服务器程序和客户机程序。典型的服务器应用程序将创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用这些远程对象的方法。而典型的客户机程序则从服务器中得到一个或多个远程对象的引用,然后调用远程对象的方法。RMI为服务器和客户机进行通信和信息传递提供了一种机制。

  在与远程对象的通信过程中,RMI使用标准机制:stub和skeleton。远程对象的stub担当远程对象的客户本地代表或代理人角色。调用程序将调用本地stub的方法,而本地stub将负责执行对远程对象的方法调用。在RMI中,远程对象的stub与该远程对象所实现的远程接口集相同。调用stub的方法时将执行下列操作:

  (1) 初始化与包含远程对象的远程虚拟机的连接;

  (2) 对远程虚拟机的参数进行编组(写入并传输);

  (3) 等待方法调用结果;

  (4) 解编(读取)返回值或返回的异常;

  (5) 将值返回给调用程序。为了向调用程序展示比较简单的调用机制,stub将参数的序列化和网络级通信等细节隐藏了起来。在远程虚拟机中,每个远程对象都可以有相应的skeleton(在JDK1.2环境中无需使用skeleton)。Skeleton负责将调用分配给实际的远程对象实现。它在接收方法调用时执行下列操作:(1) 解编(读取)远程方法的参数;(2) 调用实际远程对象实现上的方法;(3) 将结果(返回值或异常)编组(写入并传输)给调用程序。stub和skeleton由rmic编译器生成。

  利用RMI编写分布式对象应用程序需要完成以下工作:(1) 定位远程对象。应用程序可使用两种机制中的一种得到对远程对象的引用。它既可用RMI的简单命名工具rmiregistry来注册它的远程对象,也可以将远程对象引用作为常规操作的一部分来进行传递和返回。(2)与远程对象通信。远程对象间通信的细节由RMI处理,对于程序员来说,远程通信看起来就像标准的Java方法调用。(3)给作为参数或返回值传递的对象加载类字节码。因为RMI允许调用程序将纯Java对象传给远程对象,所以,RMI将提供必要的机制,既可以加载对象的代码又可以传输对象的数据。在RMI分布式应用程序运行时,服务器调用注册服务程序以使名字与远程对象相关联。客户机在服务器上的注册服务程序中用远程对象的名字查找该远程对象,然后调用它的方法。

 

以上是百度对RMI的描述. 接下来是我的例子:

---------------------------------------------------------

//用于在客户端与服务端间传送的参数对象,必须实现Serializable 接口

package server.entity;

import java.io.Serializable;

public class Student implements Serializable {

 private static final long serialVersionUID = -7937279105651707960L;

 private String name;
 private int age;
 
 public Student(String name,int age){
  this.name=name;
  this.age=age;
 }

 @Override
 public String toString() {
  String result = "my name is: "+this.name+"   my age is: "+this.age;
  return result;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }
 
}

 

//远程对象接口

package server.service;

import java.rmi.Remote;

import server.entity.Student;

public interface IRemoteService extends Remote {

 public Student fullfillStudent(Student student)throws java.rmi.RemoteException;
 
 public Student createStudent(String name,int age) throws java.rmi.RemoteException;
 
 public String sayHello(String name) throws java.rmi.RemoteException;
}

//远程对象

package server.service.impl;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import server.entity.Student;
import server.service.IRemoteService;

public class RemoteServiceImpl extends UnicastRemoteObject implements IRemoteService {

 public RemoteServiceImpl() throws RemoteException {
  super();
 }

 private static final long serialVersionUID = -5321327076322429303L;

 @Override
 public Student createStudent(String name,int age) {
  
  return new Student(name,age);
 }

 @Override
 public String sayHello(String name) {
  
  return "hi~, "+name;
 }

 @Override
 public Student fullfillStudent(Student student) {
  student.setName("default");
  student.setAge(111);
  return student;
 }

}

 

//服务端的Server,注册一个远程对象并进行绑定,之后就等客户端发送请求

package server;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import server.service.IRemoteService;
import server.service.impl.RemoteServiceImpl;

public class Server {


 public static void main(String[] args) {
  try {
   //System.setSecurityManager(new RMISecurityManager());
   IRemoteService impl = new RemoteServiceImpl();
   LocateRegistry.createRegistry(2099);
   Naming.rebind("rmi://127.0.0.1:2099/yyb", impl);
   
  } catch (RemoteException e) {
   e.printStackTrace();
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }
 }

}

//客户端,向服务端发送请求

package client;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import server.entity.Student;
import server.service.IRemoteService;

public class Client {

 
 public static void main(String[] args) {
  try {
   
   IRemoteService server = (IRemoteService) Naming.lookup("rmi://127.0.0.1:2099/yyb");
   Student stu1 = server.fullfillStudent(new Student());   
   Student stu2 = server.createStudent("b",2);
   System.out.println("fullfillStudent----"+stu1);
   System.out.println("createStudent----"+stu2);
   System.out.println(server.sayHello("everybody"));
   
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (RemoteException e) {
   e.printStackTrace();
  } catch (NotBoundException e) {
   e.printStackTrace();
  }
  

 }

}

 

至此,rmi所需的类已备齐,然后就是编译了。编译后,还要在命令行中定位到编译后的类根目录,然后rmic server.service.impl.RemoteServiceImpl 生成Stub。

 

以上是通过原生java来实现rmi,下面是通过spring来实现的。

-----------------------------------------------------------------------------

 

//远程对象,这里一定要注意,它不能extends UnicastRemoteObject, 因为UnicastRemoteObject的默认构造函数调用了UnicastRemoteObject.exportObject(Remote obj, int port)。而RmiServiceExporter的prepare方法也调用了UnicastRemoteObject.exportObject(Remote obj, int port),所以会抛异常的。

 

 

package server.service.impl;

import server.entity.Student;
import server.service.IRemoteService;

public class RemoteServiceImpl_spring implements IRemoteService {


 @Override
 public Student createStudent(String name,int age) {
  
  return new Student(name,age);
 }

 @Override
 public String sayHello(String name) {
  
  return "hi~, "+name;
 }

 @Override
 public Student fullfillStudent(Student student) {
  student.setName("default");
  student.setAge(111);
  return student;
 }

}

//服务端的applicationContext_server.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 <bean id="remoteService" class="server.service.impl.RemoteServiceImpl_spring"></bean>
 
 <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
     <property name="serviceName" value="yyb"/>
     <property name="service" ref="remoteService"/>
     <property name="serviceInterface" value="server.service.IRemoteService"/>
     <!--
     <property name="registryHost" value="127.0.0.1"/>
      -->
     <property name="registryPort" value="2099"/>
 </bean>
 
</beans>

 

//服务端的Server,读取applicationContext_server.xml,之后就等客户端发送请求

package server;

import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Server_spring {


 public static void main(String[] args) {
  
  new FileSystemXmlApplicationContext("src/server/applicationContext_server.xml");  

 }

}

//客户端的applicationContext_client.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 <bean id="rmiService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
  <property name="serviceUrl" value="rmi://127.0.0.1:2099/yyb"></property>
  <property name="serviceInterface" value="server.service.IRemoteService"></property>
 </bean>
 
</beans>

 

//客户端,向服务端发送请求

package client;

import java.rmi.RemoteException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import server.entity.Student;
import server.service.IRemoteService;

public class Client_spring {


 public static void main(String[] args) {
  ApplicationContext ac = new FileSystemXmlApplicationContext("src/client/applicationContext_client.xml");
  IRemoteService server = (IRemoteService) ac.getBean("rmiService");

  try {
   Student stu1 = server.fullfillStudent(new Student());
   Student stu2 = server.createStudent("b",2);
   System.out.println("fullfillStudent----"+stu1);
   System.out.println("createStudent----"+stu2);
   System.out.println(server.sayHello("everybody"));
   
  } catch (RemoteException e) {
   e.printStackTrace();
  }   

 }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring为各种远程访问技术提供集成工具类。Spring远程访问通过使用普通POJOs,能更容易的开发远程访问服务。目前,Spring远程访问的主要技术如下: 1. 远程调用RMI(Remote Method Invocation): 通过使用 RmiProxyFactoryBean 和 RmiServiceExporter,并且,Spring支持两个传统的RMI(使用 java.rmi.Remote接口和java.rmi.RemoteException)和通过RMI调用器实现的暴露远程调用(支持任何Java接口)。 2. Spring的HTTP调用器(Spring’s Http Invoker): Spring提供了一种特殊的允许通过HTTP进行Java串行化的远程调用策略,支持任意Java接口(就像RMI调用器)。相对应的支持类是 HttpInvokerProxyFactoryBean和 HttpInvokerServiceExporter。 3. Hessian: 通过 HessianProxyFactoryBean 和 HessianServiceExporter,可以使用Caucho提供的基于HTTP的轻量级二进制协议来透明地暴露服务。 4. Burlap: Burlap是Caucho的另外一个子项目,可以作为Hessian基于XML的替代方案。Spring提供了诸如 BurlapProxyFactoryBean 和 BurlapServiceExporter 的支持类。 5. JAX RPC: Spring通过JAX-RPC为远程Web服务提供支持(J2EE 1.4's web service API)。 6. JAX-WS:Spring通过JAX-WS为远程Web服务提供支持(the successor of JAX-RPC, as introduced in Java EE 5 and Java 6)。 7. JMS:远程访问通过类JmsInvokerServiceExporter和JmsInvokerProxyFactoryBean使用JMS的底层协议实现。 二. 远程访问------RMI 1. RMI远程访问基本流程 1). 服务端定义远程访问接口; 2). 服务端通过RmiServiceExporter暴露服务接口 3). 客户端定义与服务端已暴露的相同接口 4). 客户端通过RmiProxyFactoryBean调用服务接口
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值