你推荐哪种Java应用程序远程访问方法?

7
我想知道将作为单独J(2)EE应用程序开发的Java模块集成的最佳方法是什么。每个模块都公开Java接口。这些Java接口与POJO实体(Hibernate)一起使用,没有DTO对象。什么是最佳的集成方式,例如一个模块远程调用另一个模块的接口?
我在考虑:EJB3、Hessian、SOAP、JMS。每种方法都有其优缺点。
各位,您有什么意见或经验?
6个回答

8
尝试使用一些远程技术,但发现它们无法普及。现在我将使用Spring remoting作为实现的抽象层。它允许您专注于编写功能并让Spring通过一些配置处理远程部分。您可以选择多种实现方式(RMI、Spring的HTTP调用程序、Hessian、Burlap和JMS)。这个抽象层意味着您可以选择一种实现方式,并在需要更改时轻松地进行替换。 有关更多信息,请参见SpringSource文档

我们在一个系统中使用这个,客户端到服务器的通信采用HTTP(出于安全原因),并且使用JMS和EJB进行服务之间的调用。 - Robin

3
标准的方法是在各个服务组件之间使用纯RMI,但这会带来共享Java接口和版本更改到域模型的问题,尤其是如果您有很多组件使用相同的类。如果这些EJB始终彼此交谈,则最好将它们放入同一VM中,并避免任何远程过程调用,因为这些服务可以使用它们的LocalInterfaces。您可能会遇到的另一件事是使用Hibernate POJOs。您可能认为这些是简单的POJOs,但在幕后,Hibernate一直在使用CGLib进行忙碌,试图执行诸如允许惰性初始化之类的操作。如果这些bean被序列化并通过远程边界传递,那么您可能会遇到奇怪的Hibernate异常抛出。就我个人而言,我更喜欢创建简单的DTO或将POJOs写成XML以在组件之间传递。我的同事们会更进一步地编写自定义的线路协议来传输数据以提高性能。最近我一直在使用MULE ESB集成各种服务组件。这非常好,因为您可以混合使用RMI、套接字、Web服务等,而无需编写大部分样板代码。

http://www.mulesource.org/display/COMMUNITY/Home


1
我忘记了我对VOs/DTOs偏好的来源 - 它是一个令人不爽的Hibernate懒加载问题,其中它们的集合实现与Hibernate会话一起序列化,但在调用代码中实际上是无意义的 - 注意这个问题。 - Nick Holt
一种快速序列化POJO的方法是使用XStream。虽然不如使用自己的XSD好,但对于向您控制的系统发送数据已足够。http://xstream.codehaus.org/ - pjp
尼克,这让我很困扰!我曾经不是VOs/DTOs的忠实粉丝,但现在开始考虑更倾向于它们了 :) - Tomasz Błachowicz
1
@Pregzt - 我认为你在使用线路协议(VOs/DTOs)和应用程序(POJOs)中使用的对象之间存在微妙的差异。我能想到最明显的一个是VOs/DTOs具有所有属性的getter和setter,而我喜欢POJOs只有真正可读写属性的setter,因为它有助于向其他开发人员传达哪些属性可以设置和不能设置。 - Nick Holt

2
为什么不选择最简单有效的方案呢?对于你的情况来说,这听起来像是EJB3或者JMS,具体取决于通信是否需要同步或异步。EJB3要远比其他方式简单,因为它是在RMI之上构建的,容器提供了所有可能需要的附加功能——安全性、事务等。假设你的POJO位于共享jar中,因此可以在EJB之间简单地传递,尽管我更倾向于传递值对象。EJB的另一个好处是,在正确使用的情况下,它是最高效的(这只是我的个人观点;-)。
JMS略微复杂一些,但不会太多,基于异步通信的系统在并行化任务等方面具有某些优势。
Web服务的性能开销、必然的额外配置和额外的故障点使它们不值得麻烦,除非你有要求必须使用它们——例如与非Java客户端的交互或向外部提供数据。

@pjp上面的回答提醒了我为什么更喜欢DTOs——为了使延迟加载起作用,Hibernate会在各个地方使用session,最明显的是它们的集合实现。当这些对象被序列化时,Hibernate session也会被序列化,但在客户端却毫无意义,在调用时会出错。虽然有一个Hibernate.initialize(Object)方法可以解决这个问题,但我仍然更喜欢DTOs。 - Nick Holt

1
如果您需要在仅使用Java的应用程序之间进行网络通信,那么Java RMI是最好的选择。它具有最好的集成性、最高的透明度和最少的开销。
然而,如果您的一些客户端不是基于Java的,那么您可能应该考虑其他选项(Java RMI实际上有一个IIOP方言,允许它与CORBA交互,但我不建议这样做,除非是为了某些遗留代码的集成)。根据您的需求,Web服务可能是您的朋友。如果您关注网络负载,您可以选择使用Hessian进行Web服务。

1

你的意思是远程运行?也就是在不同的环境中运行,因此具有不同的可用性特征?还有网络开销吗?

如果是这样,我的第一步将是采取服务方法,暂时放下调用技术。只考虑您的服务的设计和含义。您知道它们相对昂贵,因此小而繁忙的接口往往是不好的。您知道服务系统可能会在调用之间失败,因此您可能更喜欢无状态服务。您可能需要在失败后重试请求,因此您可能更喜欢幂等服务设计。

然后考虑可用性关系。您的客户端是否可以在没有远程系统的情况下工作。在某些情况下,如果无法访问 HR 系统,则无法启用员工,因此您根本无法继续进行。在其他情况下,您可以采用“先发射再告诉我”的哲学;排队请求并稍后处理响应。

如果存在可用性依赖关系,则简单地公开同步接口似乎很合适。如果一切都是 Java EE,您可以使用 SLSB EJBs 进行操作。我倾向于概括,期望如果我的服务有用,则非 Java EE 客户端也可能需要它们。因此,SOAP(或REST)往往是有用的。现在,将 Web 服务接口添加到 SLSB 中非常简单。

但是我的宠物理论是,任何足够大的IT系统最终都需要异步通信:您需要解耦可用性约束。因此,我倾向于寻找类似JMS的关系。在您的服务前面放置一个MDB外观,或者使用SOAP / JMS并不太难。这种方法往往会突出显示可能潜伏的故障案例设计问题,JMS往往会让您思考:“假设我没有得到答案?假设我的答案来晚了?”


0

我会选择SOAP。

JMS可能更高效,但您需要为每个接口编写一个消息驱动的bean。

另一方面,SOAP带有许多有用的工具包,可以在给定EJB时生成消息定义(WSDL)和所有必要的处理程序(客户端和服务器)。

使用SOAP,您可以(但不必)处理证书安全性和公共网络上的安全连接。由于默认协议是HTTP over port 80,因此您将在防火墙等方面遇到最少的问题。 SOAP也非常适合异构客户端(在您的情况下,任何不是J2EE的东西),并且支持大多数常见语言和平台。


1
JMS旨在实现异步通信,即发送并忘记。因此,如果您需要从服务调用中获取响应,则需要两个消息通道,一个用于接收消息,另一个用于将回复发送回发送者。 - pjp
我认为SOAP存在的问题是使用这种技术需要定义XML模式,然后我可以使用它将XML绑定到对象(JAXB)。正如我在原始帖子中所述,目标是尽可能消除DTO并使用模型实体(Hibernate/JPA)。DTO的问题在于需要在DTO和实体之间进行转换。 - Tomasz Błachowicz
@pjp:不完全是这样。您可以使用涉及私有队列(用于会话)的模式来接收响应。基本上,客户端创建临时队列,为请求消息设置'ReplyTo'属性,并将消息发送到公共请求队列。响应者接收请求消息,启动逻辑,创建响应消息并将其发送到请求消息'ReplyTo'中指定的临时队列。 - Tomasz Błachowicz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接