RMI应用部署

最近在看《JAVA网络编程精解》到第十章突然迷糊了,怎么都看不懂怎么部署的,特别是在服务器与客户程序分布不同机器上的时候,java.rmi.server.codebase的时候,总是出现ClassNotFoundException。下面说说RMI应用程序的部署过程。

RMI应用由3部分组成,服务器、客户端和注册表程序,这三个程序部署由三种方式部

1.服务器、客户端和注册表程序在同一台的机器上,一般实验的时候可以使用,教材上都采用这种模式。

2.服务器与注册表程序运行在一台机器,而客户端运行在另一台机器上。下面讲的就是这种方式

3.服务器、注册表、客户端程序运行于三个不同的机器,这时就需要设置java.rmi.server.codebase=path,来让注册表程序能够通过path找到远程对象的接口类,并完成注册。实际上jdk5以后,采用动态代理生成stub类,客户端和(服务器-注册表分离时),通过java.rmi.server.codebase=path指名stub类的地址

关于java.rmi.server.codebase具体可以参考官方文档https://docs.oracle.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html

对于第二种部署方式,可以参考:https://segmentfault.com/a/1190000004494341#articleHeader22这里详细说明了两台机器上的不熟方式:关于上面链接程里有些不清楚的,我给出我的理解:

首先客户与服务器分离,分别创建java项目作为服务器和客户端

RMI应用部署_第1张图片

RMIClient

Client

RMMIServer:Hello

package com.cl.remote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello  extends Remote{

String sayHello() throws RemoteException;	
}

RMMIServer:Server 

 

package com.cl.remote;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class Server implements Hello{

	public Server() {
		super();
	}
	@Override
	public String sayHello() throws RemoteException {
		// TODO Auto-generated method stub
		return "Hello World";
	}
	
	public static void main(String[] args) {
		System.setProperty("java.security.policy",Server.class.getResource("rmi.policy").toString());
		if(System.getSecurityManager()==null){
			System.setSecurityManager(new SecurityManager());
		}
		
		try {
			Registry registry=LocateRegistry.createRegistry(1099);
			
			Server obj=new Server();
			Hello stub=(Hello) UnicastRemoteObject.exportObject(obj,1099);
			registry.bind("Hello", stub);
			System.out.println();
			 System.err.println("Server ready");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

 

RMIClient:Client

package com.cl.client;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import com.cl.remote.Hello;


public class Client {

	public static void main(String[] args) {
		//System.out.println(Client.class.getResource("rmi.policy").toString());
		//file:/E:/myprograms/WorkPlaceForEclipse_Java_NetProgram/RMIApp/bin/com/cl/rmi_test2/rmi.policy
		System.setProperty("java.security.policy",Client.class.getResource("rmi.policy").toString());
		if(System.getSecurityManager()==null){
			System.setSecurityManager(new SecurityManager());
		}
		String host = (args.length<1)?null:args[0];
		String port=(args.length<2)?"1099":args[1];
		try {
			Registry registry=LocateRegistry.getRegistry(host,Integer.parseInt(port));
			Hello stub=(Hello) registry.lookup("Hello");
			String response=stub.sayHello();
			System.out.println("response:" +response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

RMIClient:Hello

package com.cl.remote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello  extends Remote{

String sayHello() throws RemoteException;	
}

值得注意的是RMIClient和RMMIServer的Hello完全一样(包名也一样)具体客户端的接口类参考https://blog.csdn.net/gaohuanjie/article/details/38338765

客户端一定需要远程的接口类文件,因为需要在客户端调用远程类的远程方法,如果没有这个类编译是过不去的。开始我以为《JAVA网络编程精解》里提到的客户端没有服务端的类文件,以为是客户端可以没有远程接口类文件,结果最后才发现作者提到的是

如果Hello包名在客户端与服务端设置的不一样,会导致客户端Hello stub=(Hello) registry.lookup("Hello");转型时出错,因为返回的是com.cl.remote.Hello的存根类,而Client本地的Hello包名不是com.cl.remote话,是无法强转的。

rmi.policy参考https://segmentfault.com/a/1190000004494341#articleHeader22

部署过程:

1.win10上运行服务器程序:

RMI应用部署_第2张图片

因为在程序里设置了java.security.policy,不用再使用java -Djava.security.policy设置,客户端也一样。

2.lunix下部署客户端程序:

将RMIClient的bin目录拷到lunix下,如图:

RMI应用部署_第3张图片

随后输入:

其中192.168.56.1是win10主机的IP,1099是端口,可以发现lunix下输出了:

于是部署运行完成。

欢迎大家与我讨论RMI.

你可能感兴趣的:(Java)