Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 作为RmiServiceExporter(或RMI的替代方案)代理的服务的参考返回值公开_Java_Spring_Rmi - Fatal编程技术网

Java 作为RmiServiceExporter(或RMI的替代方案)代理的服务的参考返回值公开

Java 作为RmiServiceExporter(或RMI的替代方案)代理的服务的参考返回值公开,java,spring,rmi,Java,Spring,Rmi,如果我通过RMI使用RmiServiceExporter导出服务,服务调用的返回值将被序列化并通过线路发送到客户端。但是,除非我有一个简单的返回数据的服务,否则这不是很有用 我希望能够对这个返回值调用方法,并让它们在服务器上运行,而不是在客户机上运行。本质上,我希望在客户端上创建一个返回值的代理。使用RmiServiceExporter(或Spring支持的另一个远程处理选项)有什么方法可以做到这一点吗 我尝试实现一些返回值的自动包装,这就是我想到的: 在服务器端: class RmiRetu

如果我通过RMI使用
RmiServiceExporter
导出服务,服务调用的返回值将被序列化并通过线路发送到客户端。但是,除非我有一个简单的返回数据的服务,否则这不是很有用

我希望能够对这个返回值调用方法,并让它们在服务器上运行,而不是在客户机上运行。本质上,我希望在客户端上创建一个返回值的代理。使用
RmiServiceExporter
(或Spring支持的另一个远程处理选项)有什么方法可以做到这一点吗


我尝试实现一些返回值的自动包装,这就是我想到的:

在服务器端:

class RmiReturnValueStubbingExporter extends RmiServiceExporter {

    /* we can't use the Spring implementation of RmiInvocationHandler
     * because it's package protected */
    private class RmiReturnValueInvocationWrapper implements RmiInvocationHandler {
        private final Object wrappedObject;

        private RmiReturnValueInvocationWrapper(Class interf, Object wrappedObject) {
            this.wrappedObject = createProxyFor(interf, wrappedObject);
        }

        @Override
        public String getTargetInterfaceName() throws RemoteException {
            return null;
        }

        @Override
        public Object invoke(RemoteInvocation invocation) throws
                RemoteException, NoSuchMethodException, IllegalAccessException,
                InvocationTargetException {
            return RmiReturnValueStubbingExporter.this.invoke(
                    invocation, this.wrappedObject);
        }
    }

    @Override
    protected Object invoke(RemoteInvocation invocation, Object targetObject)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Object ret = maybeWrap(super.invoke(invocation, targetObject));

        if (ret instanceof Remote) {
            try {
                UnicastRemoteObject.exportObject((Remote) ret, 0);
            } catch (RemoteException e) {
                throw new InvocationTargetException(e);
            }
        }

        return ret;
    }

    private Object maybeWrap(Object superValue) {
        if (superValue instanceof OntologyTerm) {
            return new RmiReturnValueInvocationWrapper(
                    OntologyTerm.class, superValue);
        } else if (superValue instanceof List) {
            return new RmiReturnValueInvocationWrapper(
                    List.class, superValue);
        } else {
            return superValue;
        }
    }

    private Object createProxyFor(Class interf, Object object) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addInterface(interf);
        proxyFactory.addAdvice(new RemoteInvocationTraceInterceptor(getExporterName()));

        proxyFactory.setTarget(object);
        // don't make opaque, on the client we need to know the interfaces implemented
        return proxyFactory.getProxy(getBeanClassLoader());
    }
}
在客户端:

class RmiStubReturnValueProxyFactoryBean extends RmiProxyFactoryBean {

    @Override
    protected Object doInvoke(MethodInvocation methodInvocation,
                              RmiInvocationHandler invocationHandler) {

        def superValue = super.doInvoke(methodInvocation, invocationHandler)

        if (superValue instanceof java.lang.reflect.Proxy &&
                java.lang.reflect.Proxy.getInvocationHandler(superValue)
                instanceof RemoteObjectInvocationHandler) {
            RmiInvocationHandler rih = superValue

            def proxiedInterfaces = rih.invoke(
                    new RemoteInvocation('getProxiedInterfaces',
                            [] as Class[], [] as Object[]))

            def clientProxy = new ProxyFactory(proxiedInterfaces)

            clientProxy.addAdvice({ MethodInvocation invoc ->
                doInvoke(invoc, rih)
            } as MethodInterceptor)

            clientProxy.getProxy beanClassLoader
        } else {
            superValue
        }
    }
}
这似乎适用于两个级别的包装;在这种情况下,服务将返回
列表
。我怀疑这有很多问题,首先是调用
UnicastRemoteObject.exportObject
而从未回收任何东西。这里可能还缺少的另一件事是处理这些存根的传递,这些存根是客户端作为参数传递给服务的。因为参数是在客户机上创建的
Proxy
对象(包装RMI存根),我想至少服务器必须从客户机加载类,这是我想要避免的


我的问题是,是否已经实现了类似的功能(不一定使用RMI),我可以轻松指定哪些类型作为值返回并序列化,哪些类型的返回值应该存根。

如果任何远程方法的返回值是导出的远程对象,这是一个古老的问题,起源于CORBA、Jini和EJB的第一个版本等技术。这个想法大部分被抛弃了,因为它根本无法很好地扩展

由于网络开销,无法将远程对象透明地视为本地对象。由于网络延迟,在调用远程对象时,您希望在远程调用中打包最多的数据, 而在本地对象中,您更喜欢保持方法调用尽可能细粒度,以便从OO的角度来看,它们可以是最可重用的

方法可重用性和低网络开销这两个要求相互冲突,最终结果是远程对象的API总是与本地对象的API非常不同, 即使存在对远程对象进行完全透明的调用的技术

目前广泛采用的解决方案是通过有线传输,这是一种仅用于数据的对象。这可以在RMI、HTTP(REST)、SOAP或其他协议中完成

然后在每一端都可以对域模型进行一些映射,以便在其中写入服务和持久性层。另一方面,DTO模型并不意味着要跨越表示层

我的问题是,是否已经实现了类似的功能(不是 必须使用RMI),我可以很容易地指定所使用的类型 作为值返回并序列化,以及返回值的类型 应该留个存根

我想建议的第一件也是最重要的事情是,您应该摆脱
RMI
<代码>RMI在您考虑它时是相当低的级别为什么要一路回到CORBA?唯一的答案可能是您不需要Java EE
EJB
app服务器。但是您必须保持客户端和服务器JVM同步。如果不升级服务器,就不能升级客户端。您必须编写EJB应用服务器为您提供的所有服务(例如,连接池、命名和目录服务、池、请求队列、事务等)

EJB与RMI的对比

EJB构建在RMI之上。两者都暗示了Java客户机和bean。如果您的客户机需要用其他语言(例如.NET、PHP等)编写,请使用web服务或使用与平台无关的有线协议的其他语言,如HTTP或XML over HTTP或SOAP

Spring vs EJB

与Spring相比,EJB3.0中更好的选择取决于您是否喜欢POJO开发,除了ORM和JPA之外,还需要选择关系技术。EJB3.0的优点是EJB3.0是许多供应商的规范;弹簧只能从弹簧源获得。然而,弹簧非常坚固,具有很大的牵引力,不会移动。这会让你有更多的选择

WebServices

Spring的web服务模块在POJO服务接口方面非常灵活。这将允许您获得所需的概念隔离,将部署选择推迟到最后一刻,并允许您在第一个想法执行不好时改变主意。Web服务在理论上很好,但有一些问题需要注意:

  • 延迟。Fowler的分布式对象第一定律:“不要!”一个由许多细粒度分布式SOAP服务组成的体系结构将是优雅、漂亮、缓慢的。分发前仔细考虑
  • 从XML到对象和从对象到对象的编组会消耗CPU周期,这些CPU周期除了允许您的客户机使用平台无关协议之外,不会提供任何业务价值
  • SOAP是一个标准,它每天都变得越来越臃肿和复杂,但它有很多工具支持。供应商喜欢它,因为它有助于推动ESB的销售。REST很简单,但不太容易理解。工具不支持它

最后,我建议使用SpringWeb服务

谢谢,但即使是这样,也没有真正帮助我。我希望能够作为存根发送到客户端的对象数量是无限的。它们是从显式导出的服务创建的。我想要的是能够配置