2012-05-31 103 views
1

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

服务器使用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 */ 

} 

这样,playernames在服务器端编组(通过@XmlElement -annotated getPlayerNames())。当客户收到它时,它会正确解组清单。每个人都很高兴。

不过,现在我必须维护两个基本相同的类,其中只有细微的差别出现...什么是正确做到这一点的最好方法是什么?

回答

1

直接序列化实体,并发送它们通过电线,如果你有循环引用可能会带来问题,例如或者,如果你想包括可能需要的反序列化,尤其是在JSON的附加信息。另一个问题可能是分离的实体(如果您将它们发送给客户端,实体管理器失去对实体的控制权,并且您必须在它们返回时重新挂接它们)或延迟加载(您无法延迟加载客户端)。因此,我建议在通过电线传输实体之前将实体转换为数据传输对象。有关详细信息和动机,请参阅Fowler的“企业应用程序体系结构模式”(第401页,本章的大部分内容均可通过Google图书获得)。

使用在客户端和服务器上的同一类可能是有问题的太因为他们表现不同,并可能在未来进一步发散。您可能会通过在客户端和服务器上提交相同的代码库来限制自己,或者最终导致混乱。

+0

谢谢。当然,实体是分离的,交换只是JAX-RS的本质。因为这些实体*已经是DTO了。而且,是的,在少数情况下,同一个类在客户端和服务器上的行为不同 - 我的问题的核心是如何更好地组织类。你能提供一个建议吗? – Hank

+1

我的答案的第一段是指出我反对使用实体作为DTO。我会使用单独的类。但是,如果我不够清楚,那只是一个附注。关于类的组织,如果你想在客户端和服务器上共享一些常见的行为:在包A中创建一个基类,将其扩展到服务器的A.S包和客户端的A.C。然后在服务器的相同JAR中捆绑A + A.S,为客户端捆绑A + A.C。 Maven多模块项目(一个模块用于A,一个模块用于A.C,A作为依赖项,一个用于A.S,依赖于A)可能有所帮助。 – aha

+0

感谢@aha为Maven多模块项目的想法...这是我一直在寻找几个星期的关键词。 –

相关问题