1

我负责为多个客户端提供后端功能的 Java EE 应用程序。一些客户端也是用 Java 编写的,所以我将我的实体提取到一个单独的 jar 中,服务器和客户端共享该 jar。

服务器使用 JPA2 实现持久性,使用 JAX-RS 与客户端通信,使用 JAXB 序列化到/从 XML 和 JSON。因此,(共享的)类文件包含 JPA 和 JAXB 注释。

显然,同一个对象在服务器(它是托管的 JPA 实体)和客户端(它是反序列化的 POJO)上的行为不同——尤其是在一对多关系方面。

问题:有时我想让各个方法调用的行为根据它们的执行位置而有所不同。我可以通过继承来解决这个问题,这样我就不必手动维护同一个类的两个实现了吗?

例子:

  • 一支球队有很多球员。玩家有名字。
  • 请求被映射到GET /team/<id>获得一个团队,并GET /team/<id>/<playerName>为一个团队获得一个特定的球员。
  • 对于编组和序列化,Team应保持“平坦”(不包括播放器)。但是,在序列化中包含他们的名字,以便客户端知道他们可以详细检索哪些玩家。

在服务器端,我会这样构建它:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Team {

  /* some other fields, belonging to the Team */

  @OneToMany(fetch = FetchType.LAZY, mappedBy="team")
  @XmlTransient  // don't marshall the players
  List<Player> players;

  /* getters and setters as necessary */

  @XmlElement
  public List<String> getPlayerNames() {
    List<String> names = new ArrayList<String>();
    for (Player p : getPlayers()) {
      names.add(p.getName());
    }
    return names;
  }
}

在客户端,我会将其映射到:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Team {

  /* some other fields, belonging to the Team */

  List<String> playerNames;

  public List<String> getPlayerNames() {
    return playerNames;
  }

  public void setPlayerNames(List<String> playerNames) {
    this.playerNames = playerNames;
  }

  /* getters and setters as necessary */

}

这样,玩家名称在服务器端被编组(通过@XmlElement-annotated getPlayerNames())。当客户端收到它时,它会正确地解组列表。每个人都很高兴。

但是,现在我必须维护两个基本相同的类,其中只有微小的差异......正确执行此操作的最佳方法是什么?

4

1 回答 1

1

直接序列化实体并通过网络传输它们可能会产生问题,例如,如果您有循环引用,或者如果您希望包含反序列化可能需要的其他信息,尤其是在 JSON 中。另一个问题可能是分离的实体(如果您将它们发送到客户端,实体管理器将失去对实体的控制,当它们返回时您必须重新附加它们)或延迟加载(您不能在客户端上延迟加载)。因此,我建议在通过网络传输实体之前将它们转换为数据传输对象。有关详细信息和动机,请参阅 Fowler 的《企业应用程序架构模式》(第 401 页,该章的大部分内容可通过 Google 图书获得)。

在客户端和服务器上使用相同的类也可能有问题,因为它们的行为不同,并且将来可能会进一步分化。您可能会通过在客户端和服务器上提交相同的代码库来限制自己,或者最终导致一团糟。

于 2012-05-31T09:35:32.907 回答