我想在两个类(A和B)之间共享一些信息,这两个类在不同的java程序中运行。我没有编写完整的通信协议,而是想为此目的使用java内置rmi类。目前,B类能够远程运行属于A类的方法。是否有可能在A类中使用相同的“连接”来调用B类的方法?否则我可能要实施第二次rmi服务......
BR,
马库斯
答案 0 :(得分:9)
如果B
实现Remote
,则可以将其导出并作为参数传递给A
的RMI调用。在这种情况下,不需要在RMI注册表中注册B
,因为客户端正在明确地传递对它的引用。
答案 1 :(得分:5)
我在cleint和server之间实现了2路RMI,服务器使用Registry
公开其存根以下代码将提供更好的主意
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Observable;
import java.util.Observer;
import java.net.*;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
interface ReceiveMessageInterface extends Remote
{
/**
* @param x
* @throws RemoteException
*/
void receiveMessage(String x) throws RemoteException;
/**
* @param observer
* @throws RemoteException
*/
void addObserver(Remote observer) throws RemoteException;
}
/**
*
*/
class RmiClient extends UnicastRemoteObject
{
/**
* @param args
*/
static public void main(String args[])
{
ReceiveMessageInterface rmiServer;
Registry registry;
String serverAddress = args[0];
String serverPort = args[1];
String text = args[2];
System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort);
try
{ // Get the server's stub
registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));
// RMI client will give a stub of itself to the server
Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0);
rmiServer.addObserver(aRemoteObj);
// call the remote method
rmiServer.receiveMessage(text);
// update method will be notified
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (NotBoundException e)
{
System.err.println(e);
}
}
public void update(String a) throws RemoteException
{
// update should take some serializable object as param NOT Observable
// and Object
// Server callsbacks here
}
}
/**
*
*/
class RmiServer extends Observable implements ReceiveMessageInterface
{
String address;
Registry registry;
/**
* {@inheritDoc}
*/
public void receiveMessage(String x) throws RemoteException
{
System.out.println(x);
setChanged();
notifyObservers(x + "invoked me");
}
/**
* {@inheritDoc}
*/
public void addObserver(final Remote observer) throws RemoteException
{
// This is where you plug in client's stub
super.addObserver(new Observer()
{
@Override
public void update(Observable o,
Object arg)
{
try
{
((RmiClient) observer).update((String) arg);
}
catch (RemoteException e)
{
}
}
});
}
/**
* @throws RemoteException
*/
public RmiServer() throws RemoteException
{
try
{
address = (InetAddress.getLocalHost()).toString();
}
catch (Exception e)
{
System.out.println("can't get inet address.");
}
int port = 3232;
System.out.println("this address=" + address + ",port=" + port);
try
{
registry = LocateRegistry.createRegistry(port);
registry.rebind("rmiServer", this);
}
catch (RemoteException e)
{
System.out.println("remote exception" + e);
}
}
/**
*
* @param args
*/
static public void main(String args[])
{
try
{
RmiServer server = new RmiServer();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
}
答案 2 :(得分:1)
自从我使用RMI已经有一段时间了,但是如果B类实现了java.rmi.Remote
并且将对自身实例的引用作为参数传递给了A类中的方法,那么IIRC应该接收到将在原始实例上调用存根和调用它的方法。
但是,如果你有很多这样的RMI调用,那么你可能会遇到性能问题。
答案 3 :(得分:1)
如果将B
作为参数传递给A
中的方法,然后使用该引用调用B
上的方法,我相当确定已建立反向连接,并且我很确定RMI Registry是为B
所在的JVM创建的。在某些时候,这使我们遇到了特别严格的防火墙规则的麻烦。我们的代码看起来像
Web服务器
public int uploadFile(FileItem fileItem){
return ApplicationClassLoader
.get(DocumentManager.class)
.attachFile(new RemoteInputStreamImpl(fileItem.getInputStream());
)
}
Application Server
public int attachFile(RemoteInputStream in){
...
byte[] buffer;
while((buffer = in.read(1024)) != null) // Would return null to indicate EOF
// Do some stuff
return documentId;
}
答案 4 :(得分:-1)
如果没有第二个RMI服务器,B类如何知道A类?我想你需要两台服务器。
答案 5 :(得分:-1)
两个JVM都需要实现RMI服务。但是,查看java.rmi中的各种类非常容易。
你不能做的是以某种方式使用一个RMI连接并进行双向通信。
答案 6 :(得分:-1)
某些RMI服务支持回调或侦听器,允许服务器在同一连接上异步调用客户端。 (对不起,我不记得这样做的开放库的名称,快速谷歌不是很有帮助) 标准RMI不支持此功能,您也需要将客户端公开为RMI服务。
答案 7 :(得分:-1)