Spring框架学习[Spring RMI实现远程调用](六)

2014-11-24 03:00:32 · 作者: · 浏览: 3
Exception ex) { Throwable exToThrow = ex.getTargetException(); RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow); throw exToThrow; } catch (Throwable ex) { throw new RemoteInvocationFailureException("Invocation of method [" + invocation.getMethod() + "] failed in RMI service [" + getServiceUrl() + "]", ex); } } //如果RMI stub不是RmiInvocationHandler类型 else { //使用传统的RMI调用方式 try { return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub); } catch (InvocationTargetException ex) { Throwable targetEx = ex.getTargetException(); if (targetEx instanceof RemoteException) { RemoteException rex = (RemoteException) targetEx; throw RmiClientInterceptorUtils.convertRmiAccessException( invocation.getMethod(), rex, isConnectFailure(rex), getServiceUrl()); } else { throw targetEx; } } } } //调用RmiInvocationHandler的RMI protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler) throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { //如果客户端远程调用请求是toString()方法 if (AopUtils.isToStringMethod(methodInvocation.getMethod())) { return "RMI invoker proxy for service URL [" + getServiceUrl() + "]"; } //使用RmiInvocationHandler处理RMI调用 return invocationHandler.invoke(createRemoteInvocation(methodInvocation)); }}

通过上面对RmiClientInterceptor源码分析,我们看到Spring对RMI远程调用使用以下两种方式:

(1).RMI调用器方式:

这种方式和Spring HTTP调用器非常类似,即使用RemoteInvocation来封装调用目标对象、目标方法、参数类型等信息,RMI服务器端接收到RMI请求之后直接调用目标对象的匹配方法。

(2).传统RMI调用方式:

使用JDK的反射机制,直接调用远程调用stub的方法。

5.RMI的服务端配置:

在Spring RMI服务端需要进行类似如下的配置:

[xhtml] view plaincopyprint RMI服务接口 RMI服务导出名称 1099

RMI中,基于TCP/IP协议,而不是HTTP协议来实现底层网络通信,由于RMI的网络通信已由Java RMI实现,所以这里不再使用Spring MVC的DispatcherServlet来转发客户端配置的远程调用请求URL,只需要指定RMI的TCP/.IP监听端口和服务导出的名称即可。

6.RmiServiceExporter导出RMI远程调用对象:

RmiServiceExporter主要功能是将服务端远程对象提供的服务导出供客户端请求调用,同时将导出的远程对象和注册器绑定起来供客户端查询,其主要源码如下:

[java] view plaincopyprint public class RmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean { //导出的RMI服务名称 private String serviceName; //RMI服务端口 private int servicePort = 0; //RMI客户端socket工厂 private RMIClientSocketFactory clientSocketFactory; //RMI服务端socket工厂 private RMIServerSocketFactory serverSocketFactory; //注册器 private Registry registry; //注册主机 private String registryHost; //注册端口 private int registryPort = Registry.REGISTRY_PORT; //客户端注册socket工厂 private RMIClientSocketFactory registryClientSocketFactory; //服务端注册socket工厂 private RMIServerSocketFactory registryServerSocketFactory; //总是创建时注册 private boolean alwaysCreateRegistry = false; //替换已有的绑定 private boolean replaceExistingBinding = true; //导出的远程对象 private Remote exportedObject; //创建注册 private boolean createdRegistry = false; //注入服务端配置的RMI导出服务名称,格式为:“rmi://host:post/NAME” public void setServiceName(String serviceName) { this.serviceName = serviceName; } //设置服务端口 public void setServicePort(int servicePort) { this.servicePort = servicePort; } //设置RMI客户端socket工厂 public void setClientSocketFactory(RMIClientSocketFactory clientSocketFactory) { this.clientSocketFactory = clientSocketFactory; } //设