1、JDK的rmi
JDK其实已经帮我们封装好一堆可以用的rmi轮子,下面我就说一下,我用JDK实现一个RMI的实例。
1.1实体类
首先我们应该有一个实体类,必须实现serialzable接口。
package rmi.model;
import java.io.Serializable;
//注意对象必须实现Serializable
public class PersonEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6318564343653010223L;
/**
*
*/
private int id;
private String name;
private int age;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
1.2 服务接口及其实现
远程方法调用必须继承Remote类
package rmi.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
import rmi.model.*;
//此为远程对象调用的接口,必须继承Remote类
public interface PersonService extends Remote {
public List<PersonEntity> GetList() throws RemoteException;
public void fuck() throws RemoteException;
}
服务类的实现:
package rmi.serviceImpl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
import java.util.List;
import rmi.model.PersonEntity;
import rmi.service.*;
//此为远程对象的实现类,须继承UnicastRemoteObject
public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {
/**
*
*/
private static final long serialVersionUID = -7407879898651578373L;
public PersonServiceImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
@Override
public List<PersonEntity> GetList() throws RemoteException {
// TODO Auto-generated method stub
System.out.println("Get Person Start!");
List<PersonEntity> personList=new LinkedList<PersonEntity>();
PersonEntity person1=new PersonEntity();
person1.setAge(25);
person1.setId(0);
person1.setName("Leslie");
personList.add(person1);
PersonEntity person2=new PersonEntity();
person2.setAge(25);
person2.setId(1);
person2.setName("Rose");
personList.add(person2);
return personList;
}
@Override
public void fuck() throws RemoteException {
System.out.println("WTF");
}
}
1.3服务器的实现
package rmi.remotingservice;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import rmi.service.*;
import rmi.serviceImpl.*;
public class Server_Program{
public static void main(String[] args) {
try {
PersonService personService=new PersonServiceImpl();
//注册通讯端口
LocateRegistry.createRegistry(6600);
//注册通讯路径
Naming.rebind("rmi://127.0.0.1:6600/PersonService", personService);
System.out.println("Service Start!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.4客户端的实现
package rmi.remotingclient;
import java.rmi.Naming;
import java.util.List;
import rmi.model.PersonEntity;
import rmi.service.*;
public class Client_Program {
public static void main(String[] args){
try{
//调用远程对象,注意RMI路径与接口必须与服务器配置一致
PersonService personService=(PersonService)Naming.lookup("rmi://127.0.0.1:6600/PersonService");
List<PersonEntity> personList=personService.GetList();
for(PersonEntity person:personList){
System.out.println("ID:"+person.getId()+" Age:"+person.getAge()+" Name:"+person.getName());
}
personService.fuck();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
2、使用socket实现RMI
利用socket实现RMI的基本思想是,server端相当于一个 Skeleton(骨架)它不断地接受来自客户端的请求(远程方法调用),Skeleton在本地调用远程客户端要调用的方法,执行后将结果写入流中,通过流将结果发送给客户端。
客户端stub(存根)调用服务器端的方法的实现是:将要调用方法的名字和其他参数通过流传递给server(skeleton),server解析流中的方法名称和参数,执行后将结果写入流中,客户端再从流中得到方法运行的结果。这样远程方法的调用就完成了。
2.1 model
package model;
import java.io.Serializable;
public interface Person extends Serializable{
public int getId() throws Throwable;
public String getName() throws Throwable;
}
2.2 服务类(实际要调用方法的类)实现了person接口
package server;
import model.Person;
public class PersonServer implements Person{
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private String name;
public PersonServer(String name, int id) {
this.name = name;
this.id = id;
}
@Override
public int getId() throws Throwable {
return id;
}
@Override
public String getName() throws Throwable {
return name;
}
}
2.3 Server (Skeleton(骨架))
package skeleton;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import server.PersonServer;
public class Person_Skeleton extends Thread {
private PersonServer myServer;
public Person_Skeleton(PersonServer server) {
// 实现一个personServer实例
this.myServer = server;
}
public void run() {
try {
//建立一个ServerSocket,监听9000端口
@SuppressWarnings("resource")
ServerSocket serverSocket = new ServerSocket(9000);
//接受来自客户端的连接
Socket socket = serverSocket.accept();
while (socket != null) {
// 接受stub(存根的请求)
ObjectInputStream inStream = new ObjectInputStream(
socket.getInputStream());
String method = (String) inStream.readObject();
// 檢查客戶要求調用的方法
if (method.equals("id")) {
// 执行server端的方法,并把结果写入流中
int id = myServer.getId();
ObjectOutputStream outStream = new ObjectOutputStream(
socket.getOutputStream());
// 这样流中就有了方法执行的结果
outStream.writeInt(id);
outStream.flush();
}
if (method.equals("name")) {
//执行server端的方法,并把结果写入流中
String name = myServer.getName();
ObjectOutputStream outStream = new ObjectOutputStream(
socket.getOutputStream());
// 这样流中就有了方法执行的结果
outStream.writeObject(name);
outStream.flush();
}
}
} catch (Throwable t) {
t.printStackTrace();
System.exit(0);
}
}
public static void main(String args[]) {
// new object server
PersonServer person = new PersonServer("cxt", 2707);
Person_Skeleton skel = new Person_Skeleton(person);
skel.start();
}
}
2.4 Stub(存根)
package stub;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import model.Person;
//客户端其实存根(stub)也就相当于客户端,是存根去调用server端的方法然后得到结果的
public class Person_Stub implements Person {
/**
*
*/
private static final long serialVersionUID = -2926842299238164000L;
private Socket socket;
public Person_Stub() throws Throwable {
// 連接server 地址127.0.0.1:9000
socket = new Socket("127.0.0.1", 9000);
}
@Override
public String getName() throws Throwable {
//向流写出请求
ObjectOutputStream outStream = new ObjectOutputStream(
socket.getOutputStream());
outStream.writeObject("name");
outStream.flush();
//向流读入server写出的数据
ObjectInputStream inStream = new ObjectInputStream(
socket.getInputStream());
//然后返回
return (String) inStream.readObject();
}
@Override
public int getId() throws Throwable {
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream());
out.writeObject("id");
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
return in.readInt();
}
}
2.5 测试
package client;
import model.Person;
import stub.Person_Stub;
//客户端其实存根(stub)也就相当于客户端,是存根去调用server端的方法然后得到结果的
public class PersonClient {
public static void main(String[] args) {
try {
while(true){
//搞一个存根出来,执行方法得到server端执行后的数据
Person person = new Person_Stub();
int id = person.getId();
String name = person.getName();
System.out.println(name + " is " + id + " years old");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
完!