【问题标题】:Spring Hateoas issues rendering HAL contentSpring Hateoas 问题渲染 HAL 内容
【发布时间】:2020-12-09 19:30:12
【问题描述】:

我一直在检查类似的问题,但没有找到任何解决我所观察到的问题的答案。

问题是,当我检索 1 个资源时,我很容易在我的 REST API 中获得 HAL 格式的超媒体,但是当我点击控制器方法检索实体列表时,超媒体就不一样了。

以下是输出:

  • 返回单个资源

    "_links": { “自己”: { “href”:“http://localhost:8080/celsvs/api/books/123567891099” }, “书”:{ "href": "http://localhost:8080/celsvs/api/books" } }

  • 资源列表

    “链接”:[ { “rel”:“自我”, “href”:“http://localhost:8080/celsvs/api/books/123567891099” }, { “rel”:“书籍”, "href": "http://localhost:8080/celsvs/api/books" } ]

我从 Spring hatoas 0.25 开始,但无论如何我都必须提升 Spring boot,并且我看到 Hateoas API 发生了变化,我现在使用的是 Spring hateoas 1.0... 即使在将我的代码调整为新的 API 之后,我我仍然得到相同的结果。

我正在使用 RepresentationModelAssemblerSupport 类来保持我的控制器不受代码影响以生成讨厌的内容。这就是它的样子:

@Component
public class BookModelAssembler extends RepresentationModelAssemblerSupport<BookDto, BookDto> {

    public BookModelAssembler() {
        super(BooksController.class, BookDto.class);
    }

    @Override
    public BookDto toModel(BookDto entity) {
        return entity.add(linkTo(methodOn(BooksController.class).getResource(entity.getIsbn())).withSelfRel())
                     .add(linkTo(methodOn(BooksController.class).getAllResources()).withRel("books"));
    }
    
}

而在 Controller 中,检索一个或所有资源的端点:

@Override
@GetMapping(value = {QueryConstants.BOOKS_ISBN_PATH, QueryConstants.BOOKS_SIG_PATH})
public BookDto getResource(@PathVariable("isbn") final String isbn) {
    
    return this.modelAssembler.toModel(this.findOneResource(isbn));
}


// GET - retrieve all resources

@Override
@GetMapping (produces = { "application/hal+json" })
public List<BookDto> getAllResources() {
    
    return (findAllResources().stream().map(this.modelAssembler::toModel).collect(Collectors.toList()));
}

如您所见,即使返回列表中的所有实体都已使用方法 getResource() 中使用的相同方法 toModel() 映射,渲染的超媒体也是不同的。

我设法在所有资源的情况下看到正确的 HAL 格式返回的唯一方法是当我更改控制器的实现以返回集合模型时:

//@GetMapping
public CollectionModel<BookDto> getAll() {
        return this.modelAssembler.toCollectionModel(findAllResources());
}

但是所有实体都捆绑在一个 _embedded 元素中,当我返回实体集合时,这不是我想要的。

Spring Hateoas 文档指出 HAL 是默认设置,所以我暂时没有考虑配置任何内容...

所以,我只看到:

  • 我缺少一些配置,这样当我可以得到一组呈现的实体时(不在 _embedded 元素下)...但我没有看到任何适合 HalConfiguration bean 的东西。
  • 我假设返回请求的资源类型集合的正确方法不在 _embedded 属性内...但也许我错了。到目前为止,我的理解是,当您请求资源 Person 并且您想要返回它的联系人时,这些联系人也可以通过他们自己的端点直接访问,然后您将这些联系人与其他 Person 属性一起嵌入返回的内容中......我没有找到任何说明集合应该在 _embedded 属性中呈现的内容。

有人有什么建议吗?我的时间和想法都用完了,实现客户端的团队正在等待使用超媒体内容。 谢谢!

【问题讨论】:

    标签: java spring spring-mvc spring-hateoas hateoas


    【解决方案1】:

    HAL specification 表示属性_embedded 用于存储资源对象数组。

    编辑: 在自己的回答中回答阿尔贝托的问题

    不过,如果有人能告诉我为什么在之前的实现中附加的链接没有遵循 HAL 格式,我将不胜感激。谢谢

    Spring HATEOAS 自定义 RepresentationModel 的 JSON 序列化,它是 CollectionModel 的父类。

    // org.springframework.hateoas.mediatype.hal.RepresentationModelMixin
    public abstract class RepresentationModelMixin extends RepresentationModel<RepresentationModelMixin> {
    
        @Override
        @JsonProperty("_links")
        @JsonInclude(Include.NON_EMPTY)
        @JsonSerialize(using = Jackson2HalModule.HalLinkListSerializer.class)
        @JsonDeserialize(using = Jackson2HalModule.HalLinkListDeserializer.class)
        public abstract Links getLinks();
    }
    

    @JsonProperty("_links") 将 JSON 属性名称定义为 _links。 @JsonSerialize 定义要使用的序列化程序。查看方法org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize 的序列化逻辑。

    【讨论】:

      【解决方案2】:

      在阅读了更多内容后,我下定决心,并得出结论,在响应中发回的正确内容是 _embedded 元素内的集合。

      我已经关注了几个参考:

      • JSON HAL rfc draft 的第 6 节(这是我找到的最新版本),有一个作为资源列表请求的结果返回的文档示例,其中资源列表嵌入在_embedded 元素内的数组。
      • 在其他作者专用于 Collections 的部分中,解释是相同的,集合的元素在 _embedded 属性中返回。

      因此,与此一致,如果我将控制器更改为返回 CollectionModel,那么我将获得以 HAL 格式格式化的正确内容。

      代码是:

      @GetMapping 
      public CollectionModel<BookDto> getAll() {
          
          return this.modelAssembler.toCollectionModel(findAllResources()).add(linkTo(methodOn(BooksController.class).getAll()).withSelfRel());
      }
      

      结果是:

      {
      "_embedded": {
          "bookDtoList": [
              {
                  "isbn": "123567891099",
                  "signature": "AA-23-EEE",
                  "title": "Electromagnetismo",
                  "subtitle": "Introducción a las aplicaciones del electromagnetismo",
                  "authors": [
                      "Idoia Mendieta",
                      "Bonifacio Pérez"
                  ],
                  "available": false,
                  "numOfCopies": 0,
                  "library": null,
                  "detailedInfo": null,
                  "_links": {
                      "self": {
                          "href": "http://localhost:8080/celsvs/api/books/123567891099"
                      },
                      "books": {
                          "href": "http://localhost:8080/celsvs/api/books"
                      }
                  }
              },
              {
                  "isbn": "123567891012",
                  "signature": "AA-23-EFD",
                  "title": "Electromagnetismo",
                  "subtitle": "Introducción a las aplicaciones del electromagnetismo",
                  "authors": [
                      "Idoia Mendieta",
                      "Bonifacio Pérez"
                  ],
                  "available": false,
                  "numOfCopies": 0,
                  "library": null,
                  "detailedInfo": null,
                  "_links": {
                      "self": {
                          "href": "http://localhost:8080/celsvs/api/books/123567891012"
                      },
                      "books": {
                          "href": "http://localhost:8080/celsvs/api/books"
                      }
                  }
              }
          ]
      },
      "_links": {
          "self": {
              "href": "http://localhost:8080/celsvs/api/books"
          }
      }
      

      }

      不过,如果有人能告诉我为什么在之前的实现中附加的链接没有遵循 HAL 格式,我将不胜感激。谢谢

      【讨论】:

      • 我编辑我的答案以在此答案下回答您的新问题。
      猜你喜欢
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多