Spring中有没有简单的HATEOAS + Pagination实现,无需数据休息?

syl*_*yum 7 java rest spring hateoas spring-hateoas

我已经搜索了几天关于如何实现包含 HATEOAS 链接 + 使用 Spring boot 和 JPA 分页(无 spring 数据休息)的 Spring REST API,如下随机示例:

\n
{\n    "_links": {\n        "first": {\n            "href": "http://localhost:8080/api/albums-list?page=0&size=2&sort=title,desc"\n        },\n        "prev": {\n            "href": "http://localhost:8080/api/albums-list?page=0&size=2&sort=title,desc"\n        },\n        "self": {\n            "href": "http://localhost:8080/api/albums-list?page=1&size=2&sort=title,desc"\n        },\n        "next": {\n            "href": "http://localhost:8080/api/albums-list?page=2&size=2&sort=title,desc"\n        },\n        "last": {\n            "href": "http://localhost:8080/api/albums-list?page=4&size=2&sort=title,desc"\n        }\n    },\n    "page": {\n        "size": 2,\n        "totalElements": 10,\n        "totalPages": 5,\n        "number": 1\n    },\n    "_embedded": {\n        "albums": [\n            {\n                "id": 7,\n                "title": "Top Hits Vol 7",\n                "description": "Top hits vol 7. description",\n                "releaseDate": "10-03-1987",\n                "actors": [\n                    {\n                        "id": 4,\n                        "firstName": "Janice",\n                        "lastName": "Preston",\n                        "_links": {\n                            "self": {\n                                "href": "http://localhost:8080/api/actors/4"\n                            }\n                        }\n                    }\n                ],\n                "_links": {\n                    "self": {\n                        "href": "http://localhost:8080/api/actors/7"\n                    }\n                }\n            },\n            {\n                "id": 6,\n                "title": "Top Hits Vol 6",\n                "description": "Top hits vol 6. description",\n                "releaseDate": "10-03-1986",\n                "actors": [\n                    {\n                        "id": 3,\n                        "firstName": "Laverne",\n                        "lastName": "Mann",\n                        "_links": {\n                            "self": {\n                                "href": "http://localhost:8080/api/actors/3"\n                            }\n                        }\n                    }\n                ],\n                "_links": {\n                    "self": {\n                        "href": "http://localhost:8080/api/actors/6"\n                    }\n                }\n            }\n        ]\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然而,到目前为止我发现的解决方案非常复杂,或者样板文件的数量是可笑的\n例如这个解决方案:\n https://howtodoinjava.com/spring5/hateoas/pagination-links/\n有关的教程该页面并未完全呈现它,但它要求您创建实体、实体的模型以及充满样板的长 RepresentationModelAssemblerSupport

\n

我也尝试过:\n https://spring.io/guides/tutorials/rest/ \n但是,嵌套类(我有一对多/多对一的关系)没有获得以下链接仇恨:

\n
{\n    "id": 3,\n    "nome": "Amazonas",\n    "uf": "AM",\n    "cidades": [\n        {\n        //no HATEOAS in here\n            "id": 10003,\n            "nome": null,\n            "instituicoes": [],\n            "uf": "AM"\n        },\n        {\n            "id": 219,\n            "nome": "Alvar\xc3\xa3es",\n            "instituicoes": [],\n            "uf": "AM"\n        }\n    ],\n    "_links": {\n        "self": {\n            "href": "http://localhost:8080/api/v1/estados/estadoes/3"\n        },\n        "estadoes": {\n            "href": "http://localhost:8080/api/v1/estados/estadoes"\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我的意思是,没有更简单的解决方案吗?幸运的是,对于分页 PagingAndSortingRepository 很有用,但是同时拥有分页 + HATEOAS,真是一场噩梦。

\n

yej*_*lue 11

ARepresentationModelAssembler为必填项。extends EntityModel<T>如果您不需要其他字段,则不需要模型类。

我的示例实体类是Inventory.

表示模型汇编器。您可以在此处添加更多链接。

@Component
public class InventoryModelAssembler implements RepresentationModelAssembler<Inventory, EntityModel<Inventory>> {

    @Override
    public EntityModel<Inventory> toModel(Inventory inventory) {

        return EntityModel.of(inventory,
                linkTo(methodOn(InventoryController.class).get(inventory.getId()))
                        .withSelfRel());
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器

@RestController
@RequestMapping("/inventories")
@RequiredArgsConstructor
public class InventoryController {

    private final InventoryRepository inventoryRepository;

    private final PagedResourcesAssembler pagedResourcesAssembler;

    private final InventoryModelAssembler inventoryModelAssembler;

    @GetMapping
    public ResponseEntity get(Pageable pageable) {

        Page<Inventory> inventories = inventoryRepository.findAll(pageable);

        return ResponseEntity
                .ok()
                .contentType(MediaTypes.HAL_JSON)
                .body(pagedResourcesAssembler.toModel(inventories, inventoryModelAssembler));
    }
}
Run Code Online (Sandbox Code Playgroud)

HAL JSON 响应。完整的长响应可以在我的HTML 文档中找到。下载并使用浏览器打开。

{
  "_embedded" : {
    "inventories" : [ {
      "carrier" : "SG",
      "fltNum" : "001",
      "serviceType" : "PAX",
      "fltDate" : "2020-01-20",
      "fltDow" : 1,
      "createdDate" : "2020-06-11T13:21:44.992Z",
      "lastModifiedDate" : "2020-06-11T13:21:44.992Z",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/inventories/5ee22fe8853b0f45ae5fca27"
        }
      }
    }]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/inventories?carrier=SG&fltNum=001&page=0&size=10&sort=fltNum,asc&sort=fltDate,desc"
    },
    "self" : {
      "href" : "http://localhost:8080/inventories?carrier=SG&fltNum=001&page=0&size=10&sort=fltNum,asc&sort=fltDate,desc"
    },
    "next" : {
      "href" : "http://localhost:8080/inventories?carrier=SG&fltNum=001&page=1&size=10&sort=fltNum,asc&sort=fltDate,desc"
    },
    "last" : {
      "href" : "http://localhost:8080/inventories?carrier=SG&fltNum=001&page=1&size=10&sort=fltNum,asc&sort=fltDate,desc"
    }
  },
  "page" : {
    "size" : 10,
    "totalElements" : 20,
    "totalPages" : 2,
    "number" : 0
  }
}
Run Code Online (Sandbox Code Playgroud)

完整代码在Github中共享。如果我的项目除了这个答案之外还有帮助,请考虑在 Github 上给它一个星号。