我正在开发REST API,以便将数据从客户端应用程序传输到Web应用程序。
到目前为止一切运作良好:我在客户端应用程序中创建了我的实体对象,然后用Jersey将它们序列化为XML / JSON并调用PUT,另一端资源侦听PUT并将它们神奇地序列化为准备好的对象坚持JPA。
以下是带有注释和相关资源的实体相册的示例。
@XmlRootElement
@Entity
public class Album
{
@Id
private String id;
private String name;
@ManyToMany(cascade = CascadeType.ALL)
private Collection<Photos> photos;
// getters/setters
}
@ApplicationPath("webresources")
@Path("/album")
@Stateless
public class AlbumResource extends Application
{
@PUT
@Path("/add")
@Consumes(
{
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML
})
public Response addAlbum(Album album)
{
try
{
getAlbumEJB().create(album);
}
catch (Exception ex)
{
Logger.getLogger(AlbumResource.class.getName()).log(Level.SEVERE, null, ex);
}
if (!exception)
{
return Response.status(201).entity(album).build();
}
else
{
return Response.status(403).entity(album).build();
}
}
}
上述情况很好,尽管根据某些网站,这是“混淆模型和资源”的经典反模式(例如参见http://jacobian.org/writing/rest-worst-practices/)。 他们的理由是,上面的例子会崩溃,确实要更新一个专辑名称,我需要重新发送一个带有整个照片集的PUT,在一个更明确的例子中,我将结束发送大量无用数据只是为了纪念对象之间的关系
然而,他们没有指出常规解决方案,所以我提出了这个相当复杂的解决方案,以便将模型和资源映射到一起,从而利用自动序列化:我基本上会从客户端发送一个新实体“RESTAlbum”,而不是作为“相册”实体的照片集合,它将包含一系列照片链接:
<Album>
<id>73</id>
<name>Great Album</name>
<photosCollection>
<photo>
<href>htttp://example.com/photo/211</href>
</photo>
<photo>
<href>htttp://example.com/photo/232</href>
</photo>
</photosCollection>
</Album>
在服务器端,我将序列化RESTAlbum并根据其URL获取每个照片实体并手动构建一个我可以序列化的Album实体 与JPA。
以上是唯一的出路吗?
创建所有这些自定义类只是为了序列化关系似乎相当多的工作,奇怪的是所有的网络都充满了REST纯粹主义者,但没有人谈论这样的问题。