方法的调用都是发生在相同堆上的两个对象之间(同一台机器的Java虚拟机),如果想要调用另一台机器上的对象,可以通过Socket进行输入/输出。
远程过程调用需要创建出4种东西:服务器、客户端、服务器辅助设施、客户端辅助设施
 
RMI
Java的JMI提供客户端和服务器端的辅助设施对象(stub和skeleton,现在实际只用stub文件,客户端和服务端用一个)
辅助设施是实际执行通信的对象,他会让客户端感觉在调用本机,实际上辅助设施类似于代理,将客户端传送的信息通过Socket连接发送给服务端辅助设施,然后服务端辅助设施解包调用真正的服务端的服务,服务辅助设施取得结果后将他通过Socket连接返回给客户端辅助设施,客户端辅助设施解开这些信息传给客户端
 
远程的服务调用是通过java.rmi.registry来实现的。它提供了RMI注册表的一个类和两个接口,注册表绑定字符串名称和远程对象,可以通过注册表调用远程服务的某个对象
 
服务器端的service实现了远程调用的真正方法
 
Client辅助设施和Service辅助设施是同一个文件,在服务器端生成的
 
创建远程服务
 
大致步骤如下图所示:
 
步骤1:创建Remote接口
定义客户端会调用的方法,stub和服务都会实现此接口。远程接口定义了客户端可以远程调用的方法。
 
import java.rmi.*;
public interface MyRemote extends Remote{
     public String sayHello() throws RemoteException;
}
 
说明:
1.接口必须继承Remote
2.远程调用是有风险的,需要通过抛出一个RemoteException异常强迫客户端注意到这件事
3.远程方法的参数和返回值必须是primitive或Serializable的
 
步骤2:实现Remote接口
这个是真正执行的类,实现接口上的方法,也是客户端会调用的对象,去执行真正的工作
public class MyRemoteImp1 extends UnicastRemoteObject implements MyRemote{
     public MyRemoteImp1() throws RemoteException{}//UnicastRemoteObject会抛出RemoteException异常,构造函数抛出同样异常
     public String sayHello(){//实现Remote接口的所有方法
          return "Server says,‘Hey’"
     }
}
 
说明:
1.实现Remote的接口
2.要有与远程有关的功能,可以继承UnicastRemoteObject(UnicastRemoteObject 会抛出RemoteException异常,如果调用需要构造函数也抛出同样的异常)
3.向RMI registry注册服务
只有向RMI registry注册了,才能让远程用户存取(一定要RMI registry一定要注册起来否则运行程序会失败),注册对象时RMI 会把stub加到registry中,这是客户端需要的,使用java.rmi.Naming的rebind()注册服务
try{
     MyRemote service=new MyRemoteIm1();
     Naming.rebind("Remote Hello",service);//将实现的接口类实例向RMI registry注册,帮服务命名(Remote Hello)
}catch(Exception ex){...}
 
 
步骤3:用rmic产生stub
对真正实现的类执行rmic,产生helper类(stub)
会按照命名规则在远程实现的名称后加上_Stub。
rmic MyRemoteImp1
会生成MyRemoteImp1_Stub.class文件
 
 
步骤4:启动RMI registry(rmiregistry)
用户会从此处获得代理(客户端的sub/helper对象)
需要在实现的服务类下去执行命令:rmiregistry
如果想指定端口号,可以通过【rmiregistry 端口号】来启动
 
步骤5:启动远程服务
【java 真正实现的类】启动服务,实现服务的类的实例会向RMI registry注册(注册后才能对用户提供服务)
java MyRemoteImp1
 
指定服务端口号
两种方法:一是程序中指定,二是启动rmiregistry时指定
程序中指定:
 
启动rmiregistry指定:【rmiregistry 端口号】
 
客户端实现
 
客户端获得stub对象
直接将服务器上生成的stub文件拷贝到客户端上即可
 
客户端调用远程方法
通过Naming.lookup()的静态方法寻找某台IP上注册的远程方法(通过Naming.rebind()注册),返回一个stub对象
MyRemote service=(MyRemote) Naming.lookup("rmi://127.0.0.1:服务端口号/Remote Hello");
 
如果Naming.lookup没有指定服务的端口号,则用java默认的1099端口号
 
说明:
1.客户端调用服务必须与服务端使用相同的接口类型
2.Naming.lookup()寻址的格式【rmi://服务器地址/注册的远程方法名】,返回一个stub对象
3.客户端本地一定要有服务端rmic产生的stub类,否则RMI registry返回的stub对象不会被解序列化
 
 
RMI的注意事项
1.在启动远程服务前(java 实现服务的类),必须先启动rmiregistry
2.参数和返回类型必须是可序列化的
3.将stub类交给客户端
4.客户端和服务端一定要能够ping通,否则不能调用
 
遇到的问题
问题:
客户端启动时提示地址非法:java.net.MalformedURLException: invalid URL String: rmi://127.0.0.1:2000/Remote Hello
 
解决方法:
将远程的服务地址转换一下编码格式
String url="rmi://127.0.0.1:2000/Remote Hello";
url= URLEncoder.encode(url, "UTF-8");
MyRemote service=(MyRemote) Naming.lookup(url);
 
 
 

java基础十一[远程部署的RMI](阅读Head First Java记录)的更多相关文章

  1. java基础四 [构造器和垃圾回收](阅读Head First Java记录)

    本章讲解了对象的创建到被回收的过程,讲述了对象的生命周期   堆(heap)与栈(stack) 实例变量:实例变量是只声明在类下,方法外的变量(实例变量默认值为0/0.0/false,引用的默认值为n ...

  2. Java基础(十一) Stream I/O and Files

    Java基础(十一) Stream I/O and Files 1. 流的概念 程序的主要任务是操纵数据.在Java中,把一组有序的数据序列称为流. 依据操作的方向,能够把流分为输入流和输出流两种.程 ...

  3. Java基础十一--多态

    Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. /* 对象的多态性. class 动物 {} class 猫 ...

  4. java基础十[包、Jar存档文件和部署](阅读Head First Java记录)

    将Java的class文件生成为可执行的Java应用程序.Java应用程序有三种:完全在本机执行的Jar(例如本机的GUI可执行程序):完全在服务器端远程执行的(例如浏览器来进行存取):介于两者之间的 ...

  5. JAVA 基础开发环境 vscode 搭建 Windows下VSCode编译运行简单java

    JAVA 基础开发环境 vscode 搭建 来源 https://www.cnblogs.com/freewsf/p/7744728.html 对于使用 Visual Studio Code 的 Ja ...

  6. 003java面试笔记——【java基础篇】从团八百失败面试总结的java面试题(未完待续)

    8.java 线程     1)线程概念,线程与进程      线程:线程是“进程”中某个单一顺序的控制流.也被称为轻量进程.线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程.线 ...

  7. java基础IO流 复制键盘录入的目录,复制其中的.java文件到指定目录,指定目录中有重名,则改名 对加密文件计算字母个数

    package com.swift.jinji; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; im ...

  8. java基础(十一) 枚举类型

    枚举类型Enum的简介 1.什么是枚举类型 枚举类型: 就是由一组具有名的值的有限集合组成新的类型.(即新的类). 好像还是不懂,别急,咱们先来看一下 为什么要引入枚举类型 在没有引入枚举类型前,当我 ...

  9. java基础三 [深入多态,接口和多态](阅读Head First Java记录)

    抽象类和抽象方法 1.抽象类的声明方法,在前面加上抽象类的关键词abstract abstract class canine extends animal{      public void roam ...

随机推荐

  1. Oracle学习系列1-7

    Oracle学习系列1 两个服务必须启动: OracleOraDb10g*TNListener 和 OracleService*** 使用sqlplusw先进行环境的设置 set linesize 3 ...

  2. JavaScript 使用词法作用域,没有动态作用域

    function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面的代码,控制 ...

  3. Semantic UI 中文参考手册

    一个拥有友好词汇表的前端框架,完全语义化的前端界面开发框架,为一组开发人员之间共享UI元素配备了规格.使用的词汇(类和ID)相比其它替代品更加简洁,从而降低了学习曲线.有许多HTML元素,UI元素和场 ...

  4. 重定向 url cookie

    想象下面两行伪代码: 1. setCookie(...);2. redirect(new_web_url); 首先设置一个Cookie,然后重定向到另外一个网址,这个网址跟当前网站的域名不同 在多数情 ...

  5. PHP和Golang使用Thrift1和Thrift2访问Hbase0.96.2(ubuntu12.04)

    目录: 一.Thrift1和Thrift2的简要介绍 1) 写在前面 2) Thrift1和Thrift2的区别  二.Thrift0.9.2的安装 1) 安装依赖插件 2) Thrift0.9.2的 ...

  6. Windows性能查看器:系统的性能信息(I/O,IIS最大连接数,Sql) ,以及解决 asp.net IIS 一二百多用户并发

    在测试过程中,我们经常需要知道“系统的资源利用情况”来监测我们的测试执行情况,来查看测试环境是否有效,测试结果是否可信,或者是在无人值守时保存结果,等我们值班时再来分析. 1.在Windows环境下, ...

  7. S7-1200 与 S7-200 的对比PPT

  8. 在 Windows上配置NativeScript CLI

    1.安装Node.js,到https://nodejs.org/下载安装 2.安装Chocolatey,https://chocolatey.org/,先看一下关于chocolatey的介绍: 安装方 ...

  9. phonegap文件,目录操作以及网络上传,下载文件(含demo)

    正在做一个跨平台的应用,需要使用phonegap进行文件的一些基本操作. 需求如下:可以选择本地图片,或者从相机选择图片,并进行显示在本地,然后上传到服务器,以及可以从服务器下载图片显示出来,如果本地 ...

  10. PHP中去除字符串中的换行的方法

    在PHP中,有时候我们需要对字符串的换行进行过滤,比如天涯PHP博客中文章页面的description信息,我是直接截取的文章内容,并过滤掉html符号,最终还要过滤掉其中的换行.下面整理一下常见的去 ...