在Spring环境使用RMI时,可以省略以下几点:
1、接口类不需要继承Remote,方法不需要抛出RemoteException异常对象。
2、实现类不需要继承UnicastRemoteObject。
3、RMI服务自动注册。
下面通过具体的例子来说明其用法。
一、导出RMI服务
1、bean的配置
<beans> <bean id="syncServiceImpl" class="com.cjm.service.rmi.SyncServiceImpl" /> <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port" value="3015"/> </bean> <bean id="syncServiceProxy" class="com.cjm.service.rmi.SyncServiceRMIExporter"> <property name="service"> <ref bean="syncServiceImpl" /> <!-- 服务对象 --> </property> <property name="serviceName"> <value>hawkeyeService</value> <!-- 服务名 --> </property> <property name="serviceInterface"> <value>com.cjm.service.rmi.SyncService</value> <!-- 服务接口类 --> </property> <property name="servicePort"> <value>1099</value> </property> <!-- 服务端口 <property name="registryPort"> <value>3015</value> </property>--> <property name="registry" ref="registry"/> <property name="registryHost"> <value>${rmiServerIp}</value> </property> </bean> </beans>
2、类源码
public class SyncServiceRMIExporter extends RmiServiceExporter{
public SyncServiceRMIExporter() {
//通过系统属性设置RMI的hostname
System.setProperty("java.rmi.server.hostname", "localhost");
}
}
//RMI服务接口类
public interface SyncService{
public boolean updateMonicaSiInfos(String oldInfo, String newInfo);
}
public class SyncServiceImpl implements SyncService {
@Override
public boolean updateMonicaSiInfos(String oldInfo, String newInfo) {
oldInfo = StringUtils.trimToEmpty(oldInfo);
newInfo = StringUtils.trimToEmpty(newInfo);
if (StringUtils.isEmpty(newInfo)) {
return false;
}
......
logger.warn("成功: oldInfo=" + oldInfo + ", newInfo=" + newInfo);
return true;
}
}
二、调用RMI服务
1、bean的配置
<beans> <bean id="serviceImpl" class="RMIServiceImpl"> <property name="syncService" ref="hawkeyeService"/> </bean> <bean id="hawkeyeService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl"> <value>rmi://localhost:1099/hawkeyeService</value> <!-- RMI服务地址 --> </property> <property name="serviceInterface"> <value>com.cjm.service.rmi.SyncService</value> <!-- RMI服务接口类 --> </property> <property name="lookupStubOnStartup" value="false"/> <property name="refreshStubOnConnectFailure" value="true"/> </bean> </beans>
2、类源码
public class RMIServiceImpl {
private SyncService syncService;
public SyncService getSyncService() {
return syncService;
}
public void setSyncService(SyncService syncService) {
this.syncService = syncService;
}
public void doAction(String oldValue, String newValue)throws Exception{
boolean b = syncService.updateMonicaSiInfos(oldValue, newValue);
if(b){
System.out.println("RMI调用成功");
}else{
System.out.println("RMI调用失败");
}
}
}
通过Spring导出的RMI服务由于其接口类没有继承Romote接口,所以,在非Spring环境下调用RMI时,不是返回服务接口对象,而是返回RmiInvocationWrapper_Stub实例,然后通过反射方式来调用具体的服务方法,下面给出范例的源码供参考:
Context context = new InitialContext();
RmiInvocationWrapper_Stub stub = (RmiInvocationWrapper_Stub)context.lookup("rmi://localhost:3016/hawkeyeService");
Object[] arguments = new Object[]{"", "9999", "", ""};
Class[] parameterTypes = new Class[]{String.class, String.class, String.class, String.class};
RemoteInvocation invocation = new RemoteInvocation();
invocation.setMethodName("updateMonicaSiInfos");
invocation.setArguments(arguments);
invocation.setParameterTypes(parameterTypes);
RMIFeedback feedback = (RMIFeedback)stub.invoke(invocation);