Canonical _links with Spring HATEOAS

dke*_*ner 5 spring spring-data-jpa spring-data-rest spring-hateoas

我们正在构建一个类似于spring.io指南" 使用REST访问JPA数据 "的RESTful Web服务.要重现下面的示例输出,只需向Person添加ManyToOne -Relation,如下所示:

// ...

@Entity
public class Person {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  private String firstName;
  private String lastName;

  @ManyToOne
  private Person father;

  // getters and setters
}
Run Code Online (Sandbox Code Playgroud)

添加一些样本数据后的GET请求产生:

{
  "firstName" : "Paul",
  "lastName" : "Mustermann",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    },
    "father" : {
      "href" : "http://localhost:8080/people/1/father"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,鉴于保罗的父亲存有ID 2,我们期望的结果将是其关系的规范网址:

// ...
    "father" : {
      "href" : "http://localhost:8080/people/2"
    }
// ...
Run Code Online (Sandbox Code Playgroud)

如果对某些人是空的,这当然会引起问题(好吧,这在这里没有多大意义......;)),但在这种情况下,我们根本不想在JSON中呈现链接.

我们已经尝试实现ResourceProcessor来实现这一点,但似乎在调用处理器时尚未填充链接.我们设法添加指向所需规范网址的其他链接,但未能修改以后添加的链接.

问题:是否有一种通用的方法来定制所有资源的链接生成?

澄清我们对规范URL的需求:我们使用SproutCore Javascript框架来访问RESTful Web服务.它使用了类似"ORM"的数据源抽象,我们已经实现了Spring生成的JSON输出的通用处理程序.当查询所有人时,我们需要向具有q关系的n个人发送n*(1 + q)个请求(而不仅仅是n个)给其他人,以将它们同步到客户端数据源.这是因为默认的"非规范"链接绝对不包含有关正在设置的父亲或父亲的id的信息.这似乎会导致大量不必要的请求,如果初始响应首先包含更多信息,则可以轻松避免这些请求.

另一种解决方案是将父亲的id添加到关系中,例如:

"father" : {
  "href" : "http://localhost:8080/people/1/father",
  "id" : 2
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*our 0

您推动显示规范链接很奇怪。一旦检索到 /father 处的资源,自链接应该是规范的......但是确实没有充分的理由强制父亲关系成为规范......也许有一些缓存方案?

\n\n

对于您的具体问题...您依赖于自动生成的控制器,因此您放弃了对许多链接做出决定的权利。如果您拥有自己的 PersonController,那么您将更多地负责链接结构。如果您创建了自己的控制器,则可以使用 EntityLinks https://github.com/spring-projects/spring-hateoas#entitylinks和父亲的 ID..IE

\n\n
@Controller\n@ExposesResourceFor(Person.class)\n@RequestMapping("/people")\nclass PersonController {\n\n  @RequestMapping\n  ResponseEntity people(\xe2\x80\xa6) { \xe2\x80\xa6 }\n\n  @RequestMapping("/{id}")\n  ResponseEntity person(@PathVariable("id") \xe2\x80\xa6 ) {\n    PersonResource p = ....\n    if(p.father){\n      p.addLink(entityLinks.linkToSingleResource(Person.class, orderId).withRel("father");\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但仅仅改变 URL 似乎需要做很多工作

\n