java

位置:IT落伍者 >> java >> 浏览文章

Java远程方法调用 (4)


发布日期:2022年07月21日
 
Java远程方法调用 (4)

与现有服务器的连接

人们常说RMI主要是从Java到Java但这种说法掩盖了这样一个事实Java可使用被称为JNI的本机方法接口很容易地与现有和原有系统连接JNI和RMI的混合使用与任何其它Java程序一样简单您可使用JDBC再结合RMI与现有的关系数据库连接也就是说您可使用RMI连接二层次和三层次系统即使双方都不是用Java 编写的亦可这样做有很大的好处和优势下面会详细阐述但首先让我们看一看它是如何完成的

假定您现在有一台在关系数据库中存储了有关客户订单信息的服务器在任何多层次系统中您都得设计一个远程接口以便于客户机访问服务器利用作为Remote 接口的RMI

import javarmi*;

import javasqlSQLException;

import javautilVector;

public interface OrderServer extends Remote {

Vector getUnpaid() throws RemoteException SQLException;

void shutDown() throws RemoteException;

// other methods (getOrderNumber getShipped )

}

javasql包包含JDBC包每个远程方法均可被服务器采用实际数据库的JDBC调用或通过采用其它数据库访问机制的本机方法实现上面所示的方法返回一个Order (订单) 对象的Vector (列表)Order (订单)就是在您的系统中定义的用来保存客户订单的类

本节将介绍如何使用JDBC实现getUnpaid和如何使用JNI 实施shutDown

JDBC 连接数据库

使用JDBC实现getUnpaid的OrderServerImpl如下

import javarmi*;

import javarmiserver*;

import javasql*;

import javautilVector;

public class OrderServerImpl

extends UnicastRemoteObject

implements OrderServer

{

Connection db; // connection to the db

PreparedStatement unpaidQuery; // unpaid order query

OrderServerImpl() throws RemoteException SQLException {

db = DriverManagergetConnection(jdbc:odbc:orders);

unpaidQuery = dbpreparedStatement();

}

public Vector getUnpaid() throws SQLException {

ResultSet results = unpaidQueryexecuteQuery();

Vector list = new Vector();

while (resultsnext())

listaddElement(new Order(results));

return list;

}

public native void shutDown();

}

其中大多是JDBC任务除了以Order开始的类型是您的系统的一部分类型以外您所看到的所有类型均为JDBC或 RMI的一部分构造函数初始化OrderServerImpl对象创建与jdbc URL中所规定的数据库的连接( Connection)有了这个连接我们就可以使用prepareStatement定义一个能找到所有未付款订单的查询在此还可为其它方法定义其它查询OrderServerImpl作为数据库在同一个系统上运行而且还可能是在同一个进程中(下面将讨论shutDown)

当getUnpaid方法在RMI服务器对象OrderServerImpl上被调用后就会执行预先编译的查询并返回包含所有匹配元素的JDBC ResultSet对象随后我们为结果集中的每个项目创建新的Order对象并将其添加到Vector对象中( Java 的动态数组)在结束读取结果后我们将这个向量返回给客户机后者可将结果显示给用户或者其他相关的人

JNI 本机方法

RMI服务器和客户机可利用本机方法与现有的和原有的系统连接您可使用本机方法实现不能直接访问数据库的远程方法或者通过采用现有代码更简单地实现您可使用本机接口JNI编写C和C++程序以实现?Java方法并 Java对象上调用该方法用本机方法实现shutDown的程序如下

JNIEXPORT void JNICALL

Java_OrderServerImpl_shutDown(JNIEnv *env jobject this)

{

jclass cls;

jfieldID fid;

DataSet *ds;

cls = (*env)>GetObjectClass(env this);

fid = (*env)>GetFieldID(env cls dataSet J);

ds = (DataSet *) (*env)>GetObjectField(env this fid);

/* With a DataSet pointer we can use the original API */

DSshutDown(ds);

}

这是假定了现有服务器通过其API定义的DataSet类型得到了引用指向服务器DataSet的指针存储在dataSet域中当客户机调用shutDown时服务器的shutDown方法就会被调用因为在服务器实现中声明了要用本机方法来实现shutDown 方法所以RMI将直接调用这个本机方法这个本机方法找到对象的dataSet域得到其值并用它调用现有API 的函数DSshutDown

Sun公司目前正与ILOG公司合作开发一种称作TwinPeaks 的产品TwinPeaks将能够兼容目前的C和C++ API并生成 Java类该Java类包含了到Java类中API的调用这样您就能从Java调用现有的任何APITwinPeaks面市后将有可能完全使用Java (而非JNI调用)编写诸如shutDown这样的方法

体系结构

RMI系统可为分布式面向对象计算提供简单而又直接的基础其体系结构可允许对服务器和引用类型进行扩展从而使RMI能以连续的方式添加功能

当服务程序被输出后其引用类型就被定义在上面的例子中我们将服务器作为UnicastRemoteObject服务器输出即点到点非复制服务器对这些对象的引用对于这类服务器非常合适不同类型的服务器有不同的引用句法例如MulticastRemoteObject就有允许复制服务的引用句法

当客户机收到向服务器的引用后RMI就会下载一个可将该引用上的调用转换为面向服务器的远程调用的存根如图所示存根使用对象序列化法将参数编组到方法中并通过网络将经过编组的调用送到服务器在服务器端RMI系统接收调用并连接到一个框架上而框架则负责解除参数编组并在服务器上调用该方法的实现当服务器的执行完成后无论返回一个值或抛出一个例外框架通过对结果进行编组并向客户机的存根发送一个应答存根解除应答编组并根据需要返回一个值或抛出一个例外存根和框架是用服务器的实现生成的通常使用的是程序rmic存根使用引用与框架进行会话这种体系结构使引用能够定义通信的属性用于 UnicastRemoteObject服务器的引用与在特定主机和端口上运行的单个服务器对象进行通信凭借存根/引用的分离功能RMI就能添加新的引用类型处理复制服务器的引用可将服务器请求多路发送给一组正确的复制程序汇集响应再根据多种响应返回正确的结果如果服务程序没有在虚拟机上运行则另一个引用类型可激活该程序客户机可透明地与所有这些引用类型共同工作

保密与安全

在执行RMI请求时安全是绝对有保证的RMI可在客户机与服务器之间提供安全信道并可将下载的执行程序放入安全的沙箱(sandbox)中运行从而保护您的系统免遭不明客户机可能的攻击

首先必须定义您的安全需求这非常重要如果您正在安全的企业网内部执行诸如ComputeServer这样的程序则您只需知道谁在使用计算环路即可这样您就能对滥用系统的人进行跟蹤如果您需要提供商业计算服务器则您就需要防止多种恶意的破坏这些都会影响接口的设计在企业内部您可能只要求每个Task对象都配备人名和部门编号以便跟蹤而在商业领域中您可能需要更高的安全性包括数字签名身份识别和某些能帮助您剔除会耗费超过分配于其时间的恶意任务的合同语言

在客户机和服务器之间您可能需要有一个安全信道 RMI可使您能提供可创建包括加密插口(socket)在内的您所需要的任何类型插口的插口工厂从JDK 开始您将能够指定服务器插口所提供的服务的要求(通过给出对这些要求的描述)这种新技术可在小应用程序上采用而多数浏览器都拒绝承诺设置插口工厂插口要求可包括加密和其它要求

下载的类也存在安全问题Java通过SecurityManager对象处理安全问题而该对象可传递所有与安全有关操作的判断如打开文件和网络连接等RMI通过要求您在输出任何服务对象或在服务器上调用任何方法之前安装安全管理器以使用这个标准的Java机制RMI提供与小应用程序(无文件存取只是连接到发出主机等)限制相同的 RMISecurityManager类型这样可防止下载的执行程序从计算机上读取或写入数据或与防火墙后面的其它系统连接您也可编写和安装自己的安全管理程序对象以执行不同的安全限制

防火墙

RMI为防火墙后面的客户机提供了与远程服务器进行通信的方法这样可使您使用RMI在因特网上部署客户程序如在用于万维网上的小应用程序中穿越客户机的防火墙会使通信速度降低所以RMI成功地采用速度最快的技术连接客户机与服务器当客户机首次依次尝试下列三种可能的方法试图与服务器建立通信时该技术即被UnicastRemoteObject的引用所发现

用插口(socket)直接与服务器的端口通信

如果失败则建立连接到服务器主机和端口上的URL并在该URL上使用HTTP POST请求将信息作为POST的主体发送给框架如果成功则post的结果就是框架对存根的响应

如果又失败则用端口 (标准HTTP端口)建立连接到服务器主机的URL并使用能够将?MI请求发送给服务器的 CGI程序

这三种技术哪一种首先成功将来就会首先被用来与服务器进行通信如果这些技术都不成功则远程方法调用失败

这种三步策略使客户机能够以尽可能高的效率实现通信并大多使用直接插口连接在没有安装

上一篇:java阻塞队列 线程同步合作

下一篇:java资源获取分析