RMI(Remote Method Invocation),远程方法调用,即本地调用远程主机的服务,使用RMI能实现如同在调用本地方法似的效果,也就是说能够实现分布式应用。
一。Chat 远程方法接口需要继承Remote接口,并且远程接口的所有方法必须抛出RemoteException
package com.template.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-4
* Time: 下午9:04
*/
public interface Chat extends Remote {
void send(String message) throws RemoteException;
String receive() throws RemoteException;
}
二。ChatImpl 远程接口的实现类 需要继承UnicastRemoteObject类,并实现Chat接口
package com.template.rmi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-4
* Time: 下午9:05
*/
public class ChatImpl extends UnicastRemoteObject implements Chat {
private Logger logger = LoggerFactory.getLogger(ChatImpl.class);
protected ChatImpl() throws RemoteException {
super();
}
@Override
public void send(String message) throws RemoteException {
logger.info("Sending a message!");
logger.info(message);
logger.info("Sended a message!");
}
@Override
public String receive() throws RemoteException {
logger.info("Received a message!");
return "This is a received message content!";
}
}
三。ChatServer 远程服务注册
package com.template.rmi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-4
* Time: 下午9:10
*/
public class ChatServer implements Runnable {
private Logger logger = LoggerFactory.getLogger(ChatServer.class);
@Override
public void run() {
try {
logger.info("Server start!");
logger.info("Initialize chat service!");
ChatImpl chat = new ChatImpl();
logger.info("Bind the chat service to the server!");
Naming.rebind("chat", chat);
logger.info("Server has started the chat service!");
} catch (RemoteException e) {
logger.error(e.getMessage());
} catch (MalformedURLException e) {
logger.error(e.getMessage());
}
}
}
四。ChatClient 本地调用远程服务
package com.template.rmi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-4
* Time: 下午9:10
*/
public class ChatClient implements Runnable {
private Logger logger = LoggerFactory.getLogger(ChatClient.class);
@Override
public void run() {
try {
logger.info("Find chat service from server!");
Chat chat = (Chat) Naming.lookup("//127.0.0.1/chat");
logger.info("Sending a message to the server!");
chat.send("This is a message from client to server!");
logger.info("Sended a message to the server!");
logger.info("Receive a message from server!");
String message = chat.receive();
logger.info("The message received from server is : ");
logger.info(message);
} catch (NotBoundException e) {
logger.error(e.getMessage());
} catch (MalformedURLException e) {
logger.error(e.getMessage());
} catch (RemoteException e) {
logger.error(e.getMessage());
}
}
}
五。Main
package com.template.rmi;
/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-4
* Time: 下午10:48
*/
public class Main {
public static void main(String[] args) {
Runnable chatServer = new ChatServer();
Thread server = new Thread(chatServer);
server.run();
Runnable chatClient = new ChatClient();
Thread client = new Thread(chatClient);
client.run();
}
}
六。启动rmiregistry服务器
七。运行Main主类
八。实现效果
附:如果想要正确启动远程服务,需要对ChatImpl类进行远程方法调用的编译,即使用rmic命令,生成ChatImpl的Stub,即存根。当然,如果使用的IDE,那IDE会帮我们做这一步的。其次,为了正确使用远程服务,需要确保远程方法调用服务器在正确的位置启动,即能够找到Stub存根的目录下。启动远程方法调用,需要使用rmiregistry命令。