Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,可以让在某个 Java 虚拟机上的对象调用还有一个 Java 虚拟机中的对象上的方法。可以用此方法调用的不论什么对象必须实现该远程接口。

Java RMI不是什么新技术(在Java1.1的时代都有了),但却是是很重要的底层技术。

大名鼎鼎的EJB都是建立在RMI基础之上的,如今另一些开源的远程调用组件,其底层技术也是RMI。

在大力鼓吹Web Service、SOA的时代,是不是每一个应用都应该选用笨拙的Web Service组件来实现,通过对照測试后,RMI是最简单的,在一些小的应用中是最合适的。

以下通过一个简单的样例来说明RMI的原理和应用,以下这个样例是一个简单HelloWorld。但已涵盖RMI的核心应用与开发模式。

server上的JAVA类例如以下:

远程接口:HelloService.java

import java.rmi.Remote;
import java.rmi.RemoteException; /**
* 远程接口
* @author www.wjrong.com
*
*/
public interface HelloService extends Remote {
public String showMessage(String s) throws RemoteException;
}

远程接口实现类:HelloServiceImpl .java

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject; /**
* 远程接口实现类
* @author www.wjrong.com
*
*/
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
private static final long serialVersionUID = 1L;
public HelloServiceImpl() throws RemoteException
{
super();
}
public String showMessage(String s) throws RemoteException {
System.out.println("There is a customer call this method!"); return "Hello "+s;
}
}

远程server端启动类:SimpleServer .java

import java.rmi.Remote;
import java.rmi.RemoteException; /**
 * 远程接口
 * @author www.wjrong.com
 *
 */
public interface HelloService extends Remote {
<span style="white-space:pre"> </span>public String showMessage(String s) throws RemoteException;
}

下面是client执行的Java类:

远程接口:HelloService.java

import java.rmi.Remote;
import java.rmi.RemoteException; /**
* 远程接口
* @author www.wjrong.com
*
*/
public interface HelloService extends Remote {
public String showMessage(String s) throws RemoteException;
}

client启动类:SimpleClient .java

import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException; /**
* client启动类
* @author www.wjrong.com
*
*/
public class SimpleClient {
public static final int rmiPort=8080;
public static void main(String[] args) {
try {
Context context=new InitialContext();
HelloService helloService1=(HelloService)context.lookup("rmi://192.168.1.180:"+rmiPort+"/HelloService");
HelloService helloService2=(HelloService)context.lookup("rmi://localhost:"+rmiPort+"/HelloService");
try {
System.out.println(helloService1.showMessage("World!"));
//System.out.println(helloService1==helloService2);//一个远程对象的2个代理对象即client的2个存根地址不一样
//System.out.println(helloService1.equals(helloService2));//一个远程对象的2个代理对象即client的2个存根内容一样。都是指的一样的远程对象
} catch (RemoteException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}

測试时,先启动SimpleServer,然后启动SimpleClient

server端输出:

There is a customer call this method!

client输出:

Hello World!

简单RMI測试成功!

 

细节须要注意的地方:

1.安全管理器

当没有写策略文件覆盖C:\Program Files\Java\jre1.6.0_05\lib\security里的java.policy时,调用

if(System.getSecurityManager()==null)

System.setSecurityManager(new RMISecurityManager());

系统会抛出异常 java.security.AccessControlException。

原因:每一个Java应用都能够有自己的安全管理器,它是防范恶意攻击的主要安全卫士。

安全管理器通过执行执行阶段检查和訪问授权。以实施应用所需的安全策略。从而保护资源免受恶意操作的攻击。实际上,安全管理器依据Java安全策略文件决定将哪组权限授予类。

然而。当不可信的类和第三方应用使用JVM 时,Java安全管理器将使用与JVM相关的安全策略来识别恶意操作。在非常多情况下,威胁模型不包括执行于JVM中的恶意代码。此时Java安全管理器便没必要的。

当安全管理器检測到违反安全策略的操作时,JVM将引发 AccessControlException或SecurityException。

  在Java应用中,安全管理器是由System类中的方法setSecurityManager设置的。

要获得当前的安全管理器。能够用法 getSecurityManager。 java.lang.SecurityManager类包括了非常多checkXXXX方法。如用于推断对文件訪问权限的checkRead(String file)方法。

这些检查方法调用SecurityManager.checkPermission方法。后者依据安全策略文件推断调用应用是否有运行所请求的操作权限。假设没有,将引发SecurityException。
 假设想让应用使用安全管理器和安全策略,可在启动JVM时设定-Djava.security.manager选项。还能够同一时候指定安全策略文件。假设在应用中启用了Java安全管理器。却没有指定安全策略文件,那么Java安全管理器将使用默认的安全策略,它们是由位于文件夹$JAVA_HOME/jre /lib/security中的java.policy定义的。

类装载器用Policy对象帮助它们决定。把一段代码导入虚拟机时应该给它们什么样的权限. 不论什么时候,每个应用程序都仅仅有一个Policy对象.

2.有关rmic的疑惑rmic是为client和server端生成相关的存根和骨架(实际上就是一种代理类)。可是我们直接在javac java的过程就能够直接调用远程方法。好像没有rmic的调用。

原因:在jdk5.0曾经的版本号中。须要用rmic命令来为远程对象生成静态的代理类(包含存根和骨架类),而在jdk5.0中rmi框架会在执行的过程中自己主动为远程 对象生成动态代理类(包含存根和骨架类)。从而更彻底的封装了rmi框架的实现细节。简化了rmi框架的使用方式。

3.registry本地注冊表

为何不启动rmiregistry.exe就能完毕本地。注冊捏?实际上LocateRegistry.createRegistry(rmiPort)就是创建对远程或者本地注冊表的本地引用。创建并导出Registry实例。

Java RMI之HelloWorld程序以及相关的安全管理器的知识的更多相关文章

  1. Java RMI之HelloWorld篇

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  2. Java RMI之HelloWorld经典入门案例

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  3. 「小程序JAVA实战」小程序的springboot后台拦截器(61)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudespringboothoutailanjieqi60/ 之前咱们把 ...

  4. java jvm学习笔记四(安全管理器)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一 ...

  5. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  6. 【Java 安全技术探索之路系列:J2SE安全架构】之二:安全管理器

    作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 一 ...

  7. Java 解析epub格式电子书,helloWorld程序,附带源程序和相关jar包

    秀才坤坤出品 一.epub格式电子书 相关材料和源码均在链接中可以下载:http://pan.baidu.com/s/1bnm8YXT 包括 1.JAVA项目工程test_epub,里面包括了jar包 ...

  8. JAVA RMI helloworld入门

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  9. Java RMI简单例子HelloWorld

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

随机推荐

  1. chatops--rocketchat+hubot

    chatops--rocketchat+hubot 原文地址:http://www.cnblogs.com/caoguo/p/7221956.html 先放几张图 # rocket.chat # hu ...

  2. springMvc(初识+操作步骤)

    1.导入包2.配置web.xml <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:x ...

  3. 获取windows版本号

    原文:https://blog.csdn.net/justFWD/article/details/44856277 内容整理如下,点击跳至指定内容: manifest文件加上compatibility ...

  4. 转:函数调用的区别:_cdecl以及_stdcall

    函数调用的几个概念:_stdcall,_cdecl.... 1._stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈.VC将 ...

  5. selenium+python自动化unittest之跳过用例skip

    前言 当测试用例写完后,有些模块有改动时候,会影响到部分用例的执行,这个时候我们希望暂时跳过这些用例. 或者前面某个功能运行失败了,后面的几个用例是依赖于这个功能的用例,如果第一步就失败了,后面的用例 ...

  6. JFinal怎么更改项目服务的端口

    如图所示,运行时启动的端口是80,现在将它改成801: 可以在Debug configuration 或 Run configuration 弹出的窗口中配置,方法右击项目>properties ...

  7. pycharm connect to mysql

    1.download mysql installer community 5.7.20 https://dev.mysql.com/downloads/file/?id=473605 or 链接:ht ...

  8. mysql批量插值

    将查询结果集插入到表中(适用批量插值) 将结果集插入 不需要添加VALUES INSERT INTO `erp`.`role_menu` (`ROLEUUID`, `MENUUUID`) (SELEC ...

  9. String与常量池(JDK1.8)

    ---- 基础知识 String是final类, 并且其方法都被final修饰 String通过char数组来保存字符串 对String对象的任何操作都不会影响到原来的String对象, 所有的改变都 ...

  10. buf.values()

    buf.values() 返回:{Iterator} 创建并返回一个包含 Buffer 值(字节)的迭代器.当 Buffer 使用 for..of 声明时将自动调用该函数. const buf = B ...