代码如下:
package com.unmi;
import java.rmi.*;
/**
* 远程接口必须扩展接口java.rmi.Remote
*/
public interface HelloInterface extends Remote
{
/**
* 远程接口方法必须抛出 java.rmi.RemoteException
*/
public String say() throws RemoteException;
}
2. 实现远程接口及远程方法(继承UnicastRemoteObject)Hello.javajava 代码
package com.unmi;
import java.rmi.*;
import java.rmi.server.*;
/**
* 扩展了UnicastRemoteObject类,并实现远程接口 HelloInterface
*/
public class Hello extends UnicastRemoteObject implements HelloInterface
{
private String message;
/**
* 必须定义构造方法,即使是默认构造方法,也必须把它明确地写出来,因为它必须抛出出RemoteException异常
*/
public Hello(String msg) throws RemoteException
{
message = msg;
}
/**
* 远程接口方法的实现
*/
public String say() throws RemoteException
{
System.out.println("Called by HelloClient");
return message;
}
}
3. 启动RMI注册服务,并注册远程对象(HelloServer.java),在spring中配置 <bean id = "rmiServer" class = " com.unmi.Hello" /> <bean id = "rmiService" class = "org.springframework.remoting.rmi.RmiServiceExporter" > <property name = "serviceName" value = "rmiServer" /> <property name = "service" ref = "rmiServer" /> <property name = "serviceInterface" value = "com.unmi.HelloInterface" /> <property name = "registryPort" value = "1099" /></bean >
4. 客户端查找远程对象,并调用远程方法(HelloClient)java 代码
package com.unmi;
import java.rmi.Naming;
public class HelloClient
{
/**
* 查找远程对象并调用远程方法
*/
public static void main(String[] argv)
{
try
{
HelloInterface hello = (HelloInterface) Naming.lookup("rmiServer");
//调用远程方法
System.out.println(hello.say());
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
}
这样的本地调用是没有问题的,如果我想在另外的系统中调用rmiServer这个服务,Client端怎么写?Client端的HelloInterface从哪获取?如果我想在hello.say()方法,加上自己定义的类作为参数,Client端怎么写?Client端传入的定义类从哪获取?
解决方案 »
- Servlet中的字符问题,急急急
- 请问大家如何用表格现实数据呢,有现成的组件吗?我在struts+hibernate+myeclipse+mysql+tomcat5.5下开发的
- Saba系统
- 求助!困扰俺一个礼拜的Hibernate和Struts的问题!
- RandomAccessFile类读取和写入字节数为什么会是这样?
- OutputStream 向客户端输出时,文件名过长问题
- 用JBuilder开发CMP时怎么设置Driver和URL,急啊!
- 哪位大哥有用java写的进销存方面的例子啊,给我一份,谢谢!
- 新创建的实体类,查询所有测试时,不发sql
- spring boot热部署(springloader)
- 阿宝兄,接上一个帖子.
- js浏览器兼容问题
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface GuessTheCapitalServer extends Remote{
public boolean register(String name) throws RemoteException;
public String getCountry(String name) throws RemoteException;
public String guess(String name,String capital) throws RemoteException;
}package guessthecapital;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RMISecurityManager;
import java.rmi.Naming;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Calendar;
public class GuessTheCapitalServerApp extends UnicastRemoteObject implements
GuessTheCapitalServer{
private static ArrayList<Map> countryList=new ArrayList();
private static ArrayList<Map> playerList=new ArrayList();
public GuessTheCapitalServerApp() throws RemoteException {
super();
HashMap map=new HashMap();
map.put("country","afghanistan");
map.put("capital","kabul");
countryList.add(map); map=new HashMap();
map.put("country","australia");
map.put("capital","canberra");
countryList.add(map); map=new HashMap();
map.put("country","cambodia");
map.put("capital","phnom penh");
countryList.add(map); map=new HashMap();
map.put("country","canada");
map.put("capital","ottawa");
countryList.add(map);
......
}
public boolean register(String player) {
for(int i=0;i<playerList.size();i++){
if(playerList.get(i).get("player").equals(player.toLowerCase())){
return false;
}
}
Calendar c=Calendar.getInstance();
int i=c.get(Calendar.MILLISECOND)%29;
Map map=new HashMap();
map.put( "player",player.toLowerCase());
map.put("pos", i);
playerList.add(map);
System.out.println("Player "+player.toUpperCase()+" registered with "+(String)countryList.get(i).get("country"));
return true;
}
public String getCountry(String player) {
for(int i=0;i<playerList.size();i++){
if(((String)playerList.get(i).get("player")).equals(player.toLowerCase())){
int pos=(Integer)playerList.get(i).get("pos");
return (String)countryList.get(pos).get("country");
}
}
return "No country";
}
public String guess(String player, String capital) {
for(int i=0;i<playerList.size();i++){
if(((String)playerList.get(i).get("player")).equals(player.toLowerCase())){
int pos=(Integer)playerList.get(i).get("pos");
String currCapital=(String)countryList.get(pos).get("capital");
if(currCapital.equals(capital.toLowerCase())){
System.out.println(player.toUpperCase()+":"+((String)countryList.get(i).get("country")).toUpperCase()
+":"+((String)countryList.get(i).get("capital")).toUpperCase());
return "CORRECT: The capital of "+((String)countryList.get(i).get("country")).toUpperCase()
+" is "+capital.toUpperCase();
}
}
}
return "WRONG: Capital or Player incorrect";
} public static void main(String args[]){
System.out.println();
System.out.println("Initialising GuessTheCapitalServer ...");
if(System.getSecurityManager()==null){
System.setSecurityManager(new RMISecurityManager());
}
try{
GuessTheCapitalServer guessTheCapitalServer=new GuessTheCapitalServerApp();
Naming.rebind("GuessTheCapitalServer", guessTheCapitalServer);
System.out.println("GuessTheCapitalServer Started");
System.out.println();
}catch(Exception e){
System.out.println("GuessTheCapitalServer err:"+e.getMessage());
}
}}package guessthecapital;
import java.rmi.RMISecurityManager;
import java.rmi.Naming;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main { public static void main(String args[]) throws Exception {
if (args.length == 0) {
System.out.println("error:must input the server,like localhost.");
return;
}
System.setSecurityManager(new RMISecurityManager());
GuessTheCapitalServer guessTheCapitalServer = (GuessTheCapitalServer) Naming.lookup("//" + args[0] + "/GuessTheCapitalServer");
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
String readLine = "", player = "", inCountry = "", capital = "";
System.out.println();
while (!readLine.toLowerCase().equals("q")) {
System.out.print("Enter player name ('Q' or 'q' to exit):");
readLine = sin.readLine();
if (!readLine.toLowerCase().equals("q")) {
player = readLine;
if (guessTheCapitalServer.register(player)) {
System.out.println("Player " + player.toUpperCase() + " registered.");
} else {
System.out.println("Player has already registered.");
}
System.out.println(); inCountry = guessTheCapitalServer.getCountry(player);
System.out.print("What is the capital of " + inCountry + " ('Q' or 'q' to exit):");
readLine = sin.readLine();
if (!readLine.toLowerCase().equals("q")) {
System.out.println(guessTheCapitalServer.guess(player, readLine));
System.out.println();
}
}
}
System.out.println();
System.out.println("Terminated. Exiting...");
}
}
rmi.bat:
set classpath=%classpath%;f:\student\capitalRMI
start rmiregistryserver.bat
set classpath=%classpath%;f:\student\capitalRMI
java guessthecapital.GuessTheCapitalServerAppclient.bat
set classpath=%classpath%;f:\student\capitalRMI
java guessthecapital.Main localhost --这里localhost可以换成server的ip操作说明:
编译:cd F:\student\capitalRMIjavac -d . -cp . *.java创建安全策略:
policytool:
安全文件:.java.policy
grant {
permission java.security.AllPermission;
};生成stubset classpath=%classpath%;f:\student\capitalRMIrmic guessthecapital.GuessTheCapitalServerApp注册
start rmiregistry运行
另外打开cmdset classpath=%classpath%;f:\student\capitalRMIjava guessthecapital.GuessTheCapitalServerApp客户端
set classpath=%classpath%;f:\student\capitalRMI
java guessthecapital.Main localhost
<bean id="ClientrmiService"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceInterface">
<value>com.unmi.HelloInterface</value>
</property>
<property name="serviceUrl">
<value>rmi://10.299.101.***:1099/rmiService</value>
</property>
<property name="refreshStubOnConnectFailure">
<value>true</value></property>
<property name="lookupStubOnStartup"><value>false</value></property>
</bean>HelloInterface hello = (HelloInterface) Naming.lookup("ClientrmiService");
恩,这个我知道,我想知道是怎么实现从网络加载接口类,类似于webService的客户端一样。
能不能像webService一样,通过访问地址可以自动生成客户端?
rmi远程是把对象以二进制流的方式通过scoket协议传输远程供给终端调用,实现不同的JVM中的对象可以相互访问,但是这是有个通讯机制的,就是服务端除了要完成服务的注册以外,还要生成占位程序,也可以叫代理程序,代理程序拷贝至终端,你要调用什么服务,首先由代理提供给你,代理会把你的请求信息封装给远程,远程接收到信息后立即调用相关服务,并把返回的结果对象以二进制流的方式传输给终端,终端收到后再进行反序列化,这就是为什么发布服务的时候某些数据对象必须继承序列化接口的原因,我建议你先好好看看这些基本原理,再动手慢慢写hello world,那个时代流行一个eclipse的rmi插件,叫啥名字我忘了,你搜搜,可以实现快速发布服务和生成占位程序,如果你用过axis等webservice框架的时候一定觉得这些操作和它很像,其实axis等框架中也继承了rmi组件,在java远程调用过程中也是这么干的,你研究rmi精神确实可嘉,但是研究技术要有思路,先知道原理才好下手,祝你好运!