初学RMI时,在网上搜java RMI的使用方法,很容易就搜到了,也很简单,整个过程也就是以下几个步骤:
1、创建自定义服务接口并继承java.rmi.Remote接口
package cn.com.rimtest;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMIServerInterface extends Remote{
String getData(String name) throws RemoteException;
}
2、实现自定义的远程服务接口RMIServiceInterface
package cn.com.rimtest.impl;
import cn.com.rimtest.RMIServerInterface;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RMIServiceImpl extends UnicastRemoteObject implements RMIServerInterface{
public RMIServiceImpl() throws RemoteException {
}
@Override
public String getData(String name) throws RemoteException {
return "your name is "+name;
}
}
3、注册RMI服务,暴露接口
package cn.com.rimtest.server;
import cn.com.rimtest.impl.RMIServiceImpl;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RMIServer{
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(2342);
Naming.bind("rmi://127.0.0.1:2342/RMIServerInterface",new RMIServiceImpl());
} catch (RemoteException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (AlreadyBoundException e) {
e.printStackTrace();
}
}
}
4、客户端调用
package cn.com.rimtest.client;
import cn.com.rimtest.RMIServerInterface;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class RMIClient{
public static void main(String[] args) {
try {
RMIServerInterface rmiServerInterface = (RMIServerInterface)Naming.lookup("rmi://127.0.0.1:2342/RMIServerInterface");
String data = rmiServerInterface.getData("tom");
System.out.println(data);
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
5、运行RMIServer的main方法,启动服务;运行RMIClient的main方法,调用服务,控制台输出:
your name is tom
这种java RMI大家都会写,但是这却不是真正意义上的远程方法调用,因为在同一个java工程里,服务端和客户端都在一个项目里运行,体现不了远程。如果都在同一个项目里了,再使用RMI那就太傻了,显然实际的用法不是这样的,这只是为了演示创建和调用方式。
下面是在spring框架下使用RMI的简单案例
Spring RMI很简单,简化了RMI的实现,帮你解决了异常处理,服务接口不用继承Remote(仅仅是普通接口),服务实现类不用继承UnicastRemoteObject,不用我们自己注册rmi的远程服务实现类(XML配置)。服务器端要做的仅仅是写好需要提供远程服务的实现类,然后将其交给RmiServiceExporter类,RmiServiceExporter会将实现类发布为RMI服务
客户端也很简单,只需要使用RmiProxyFactoryBean从服务器端的URL中获取服务对象 ,然后从spring容器中获取RmiProxyFactoryBean封装的id即可。
我用的是idea,spring,springMVC,maven,jdk8做的这个案例
1、首先打开idea创建maven project,选择quickstart,项目名叫做rmidemo
实际上刚创建完后只有画红框的,这是我在全部写完这个案例时才写的博文。
2、然后在rmidemo上右键新建model也选择quickstart,名字就叫上图中的server_interface
这个项目里主要放的是接口
普通的接口,没有继承Remote接口
package com.my.rmi;
public interface RMIService{
String getData(String name);
}
3、写完时候右键rmidemo,如图:
这一步的目的是把server_interface安装到本地仓库,安装成功后会在自己本地的maven仓库看到,如下图:
为什么要安装?因为服务端要实现这个接口,客户端要拿到接口对应的实例。所以它们二者都依赖于这个接口,因此把服务接口发布到maven仓库,让二者引入依赖,遵循面向接口编程的规范,具体往下看。
4、然后继续在rmidemo上右键新建model,这时选择webapp,名字就叫上图servic_impl,在pom文件里引入刚才安装的依赖
com.my.rmi
server_interface
1.0-SNAPSHOT
RMIServiceImpl.java
package com.my.rmi;
import org.springframework.stereotype.Service;
@Service
public class RMIServiceImpl implements RMIService{
@Override
public String getData(String name) {
return "your name is "+name;
}
}
5、然后继续在rmidemo上右键新建model,这时选择webapp,名字就叫上图webtest,在pom文件里引入刚才安装的依赖和一样
TestController.java
package com.myrmi.controller;
import com.my.rmi.RMIService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController{
@Autowired
@Qualifier("rmiServiceImpl")
private RMIService rmiService;
@ResponseBody
@RequestMapping("/getData/{name}")
public String getData(@PathVariable("name") String name){
try {
return rmiService.getData(name);
} catch (Exception e) {
e.printStackTrace();
return "error";
}
}
}
6、代码都写完了,接下来就是配置了
server_interface项目里Application.xml配置如下,为什么以qqq,www命名,等下解释
servic_impl项目里spring-mvc.xml配置如下,
7、为什么以qqq,www命名,是为了更加清晰的看出来是怎么调用的,服务端和客户端的联系,
对应关系
(1)
(2)
(3)
一般这些值都是统一的写成了rmiServiceImpl,让人不知道是如何对应的,本人经过测试得到这些结论,起的名字只是为了好区分,实际应该见文识意。
8、配置web.xml
这个就不用我多说了,服务端和客户端都是web项目使用了spring框架,需配置一下加载spring配置。
另外需运行在Tomcat容器里,所以在这两个项目的pom文件里加入了maven Tomcat的插件,注意两个端口要不一样
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
9001
/
然后右键项目先启动服务后启动客户端
运行启动,两个项目都没有错误,这时候打开浏览器访问,
tips:最终的项目结构如下,你会发现两个web项目里的依赖完全一样,或者很多一样的那么你就可以把这些共同的依赖提取出来放到父项目的pom文件里