oop - 在 EJB<->JSF2 应用程序中重用服务器端和客户端的实体

标签 oop jakarta-ee ejb client-server

几周前我开始学习 EJB,我对如何在客户端和服务器端重用实体类有疑问。假设我们有 CRUD 应用程序。

  1. 服务器被编写为 EJB 并管理数据(创建、读取、更新、删除)。它使用 JPA 连接数据库。
  2. 客户端是使用 JSF2 编写的,它是一个简单的图形用户界面,使用远程 EJB 来管理数据。
  3. 两者(客户端和服务器)在不同的服务器上工作。
  4. 要使用 EJB,客户端需要有 EJB 接口(interface)和实体(需要实体来反序列化 EJB 返回的对象)。
  5. 服务器端实体有 JPA 注释。
  6. 客户端实体需要与服务器相同,但不需要 JPA 注释。
  7. (客户端和服务器)实体应该在同一个 jar 库中,因为它更容易维护。

这些是我解决问题的建议:

  1. 创建仅包含实体接口(interface)的库,以便客户端和服务器可以按照他们需要的方式实现它。
  2. 创建包含没有 JPA 注释的实体实现的库(服务器将需要使用 xml 而不是注释)。

什么是最好的解决方案?我的解决方案正确吗?如果有任何建议,我将不胜感激。

最佳答案

如果您信任客户端,或者如果您不关心是否有任何 JPA 注释泄露给客户端,您可以将 JPA 实体用作数据传输对象 (DTO)。警告:任何未被服务器获取的惰性托管关系将对客户端不可用,可能在序列化期间导致异常,或者可能查询和序列化太多东西。 (这是您的选项 1)

或者,您可以为每个实体创建 DTO。每个实体可能有许多 DTO(例如,包含论坛帖子所有字段的完整 DTO,仅包含标题、日期、作者的摘要 DTO)。您可以使用类似 Commons BeanUtils 的实用程序以反射方式从实体复制到 DTO,而无需编写大量样板代码 (dto.setTitle(entity.getTitle()); dto.setDate(entity.getDate()); ...)。在这种情况下,DTO 存在于一个单独的 JAR 中,由客户端和服务器共享,但实体存在于它们自己的部署单元中并且对服务器是私有(private)的。这是 EJB 1/2 过去最受反对的做法。 (这与您的选项 2 有一些相似之处,但您将重用 DTO 而不是实体本身)

然后您可以将服务器公开为 WEB 服务或 REST 端点(JAX-WS 和 JAX-RS 使这变得非常容易)。通过适当的配置,甚至可以在客户端中重用 JPA bean。这具有与其他技术互操作的额外好处,但可能会很慢。

您的选项 2 也是可行的,但您将增加维护 XML 部署描述符的开销(XDoclet 在这种情况下可能会有所帮助,如果它支持 JPA - 已经很多年没有使用它了)。

使用任何类型的远程处理时,请注意通信通常是昂贵的。因此,远程调用应尽可能粗粒度,并尽可能少地交换数据(因此总结了上面提到的 DTO)。

关于oop - 在 EJB<->JSF2 应用程序中重用服务器端和客户端的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18741434/

相关文章:

java - EJB 异常 : Failed to acquire the pool semaphore

java - EntityManager 注入(inject)导致 NullPointerException

接口(interface)、EJB 和 Servlet 中的 Javadoc

c# - Reflection是否违反了封装原则?

python - 我应该上课吗? (Python)

java - 注入(inject)的 JOOQ 上下文泄漏连接

java - 对 RMI 公开的 jBoss EJB 的并发远程调用是否序列化?

jakarta-ee - Java EE 企业 JavaBeans 开发人员

oop - 需要帮助理解 Go 中的 `map[String]type` 行为

java - 如何以OO方式修改返回值设计?