rmi,远程方法调用,将service通过rmi接口对外进行发布,客户端通过地址+端口远程调用服务。
项目结构(java项目即可,jdk无要求):
--src
--rim2
--CmdService.java
--CmdServiceImpl.java
--GetService.java
--SetService.java
--cfg.properties
代码:
应用服务部分:
定义一个服务接口,集成rmi的Remote接口:
package rim2;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;
public interface CmdService extends Remote {
public Map<String, String> executeCmd(String cmd) throws RemoteException;
}
服务实现:
package rim2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
public class CmdServiceImpl extends UnicastRemoteObject implements CmdService {
public CmdServiceImpl() throws RemoteException {
}
public Map<String, String> executeCmd(String cmd) throws RemoteException {
Runtime rt = Runtime.getRuntime(); // 运行时系统获取
Map<String, String> lineMap = new HashMap<String, String>();//存放返回值
try {
Process proc = rt.exec(cmd);// 执行命令
InputStream stderr = proc.getInputStream();//执行结果 得到进程的标准输出信息流
InputStreamReader isr = new InputStreamReader(stderr);//将字节流转化成字符流
BufferedReader br = new BufferedReader(isr);//将字符流以缓存的形式一行一行输出
String line = null;
while ((line = br.readLine()) != null) {
if (line!=null && !"".equals(line)) {
String[] strLine = line.split(":");
if(strLine.length>=2) {
lineMap.put(strLine[0].trim(), strLine[1].trim());
}
}
}
br.close();
isr.close();
stderr.close();
} catch (IOException e) {
e.printStackTrace();
}
return lineMap;
}
}
备注:java.rmi.server.UnicastRemoteObject类
通常,远程对象都 继承UnicastRemoteObject类,UnicastRemoteObject 类提供远程对象所需的基本行为。在这个类中提供了支持创建和导出远程对象的一系列方法,一个对象继承UnicastRemoteObject它将获得以下特性:
A、对这种对象的引用至多仅在创建该远程对象的进程生命期内有效
B、使得远程对象既有使用TCP协议通信的能力(Socket)
C、对于客户端与服务器的调用、传参、返回值等操作使用流的方式来处理
其他的,java.rmi.registry.LocateRegistry类提供了一系列的方法用于创建、获取Registry实例的方法;在Registry接口中,定义了一系列的方法,用于操作远程对象包括:绑定对象(bind)、获取对象(lookup)、重写绑定(rebind)、解除绑定(unbind)和返回注册表绑定列表(list)方法(也可以使用java.rmi.Naming来操作)。
发布服务:
package rim2;
import java.io.InputStream;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.util.Properties;
public class SetService {
public static void main(String[] args) {
try {
Properties properties = new Properties();
InputStream in = GetService.class.getClassLoader().getResourceAsStream("./cfg.properties");
properties.load(in);
String serverip = properties.getProperty("serverip");
String serverport = properties.getProperty("serverport");
String rmiString = "rmi://"+serverip+":"+serverport+"/cmdService";
CmdService studentService = new CmdServiceImpl();
LocateRegistry.createRegistry(Integer.parseInt(serverport));// 定义端口号
Naming.rebind(rmiString, studentService);
System.out.println("服务已启动");
} catch (Exception e) {
e.printStackTrace();
}
}
}
为了方便使用,ip、端口信息配置化:
cfg.properties
serverip:127.0.0.1
serverport:5008
客户端调用代码:
package rim2;
import java.io.InputStream;
import java.rmi.Naming;
import java.util.Map;
import java.util.Properties;
public class GetService {
public static void main(String[] args) {
try {
Properties properties = new Properties();
InputStream in = GetService.class.getClassLoader().getResourceAsStream("./cfg.properties");
properties.load(in);
String serverip = properties.getProperty("serverip");
String serverport = properties.getProperty("serverport");
String rmiString = "rmi://"+serverip+":"+serverport+"/cmdService";
CmdService studentService = (CmdService) Naming.lookup(rmiString);
Map<String, String> map = studentService.executeCmd("ifconfig");
for (String ket : map.keySet()) {
System.out.println(map.get(ket));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}