J'ai développé un microservice en utilisant Spring Boot. La documentation de l'API REST est faite avec Swagger. Certaines ressources REST utilisent les concepts de Spring pour permettre la pagination gratuitement. En voici un exemple:
@RequestMapping(value = "/buckets", method = GET)
public PagedResources list(Pageable pageable, PagedResourcesAssembler assembler) {
return bucketService.listBuckets(pageable, assembler);
}
Si j'ouvre la page Swagger, le formulaire suivant est disponible pour la ressource:
Le problème que j'ai est que le paramètre pageable est détecté avec content-type application/json et je ne sais pas comment passer une valeur pour changer la taille de la page par exemple. Toutes les valeurs semblent être ignorées.
Est-il possible de transmettre les paramètres de requête en tant qu'objet JSON? ou est-il possible de configurer Swagger pour générer des champs de paramètres de requête indépendants pour les accesseurs contenus dans l'interface Pageable?
Veuillez noter que j'utilise Springfox avec Gradle:
compile 'io.springfox:springfox-spring-web:2.3.1'
compile 'io.springfox:springfox-swagger2:2.3.1'
compile 'io.springfox:springfox-swagger-ui:2.3.1'
Ceci est un problème connu avec Spring-Fox. Voir le numéro # 755 . D'après le commentaire de zdila 2 , à ce moment-là, la solution consiste à ajouter @ApiImplicitParams, ce qui n'est pas idéal, mais cela fonctionne.
@ApiImplicitParams({
@ApiImplicitParam(name = "page", dataType = "integer", paramType = "query",
value = "Results page you want to retrieve (0..N)"),
@ApiImplicitParam(name = "size", dataType = "integer", paramType = "query",
value = "Number of records per page."),
@ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
value = "Sorting criteria in the format: property(,asc|desc). " +
"Default sort order is ascending. " +
"Multiple sort criteria are supported.")
})
[
1https://github.com/springfox/springfox/issues/755
2https://github.com/springfox/springfox/issues/755#issuecomment-135059871
La réponse de Vineet Bhatia avec @ApiImplicitParams
est satisfaisante. Mais j’ai fait face à une situation où @ApiIgnor
et @ApiParam(hidden = true)
ne fonctionnaient pas et que vous pouviez toujours observer les paramètres asembler et pageable. J'ai corrigé ce problème en ajoutant la ligne suivante
docket.ignoredParameterTypes(Pageable.class, PagedResourcesAssembler.class);
au haricot Docket dans ma SwaggerConfig
.
En vous appuyant sur la réponse de Vineet Bhatia, vous pouvez envelopper la solution dans une annotation personnalisée pour la réutiliser:
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@ApiImplicitParams({
@ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "Results page you want to retrieve (0..N)"),
@ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "Number of records per page."),
@ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "Sorting criteria in the format: property(,asc|desc). "
+ "Default sort order is ascending. " + "Multiple sort criteria are supported.") })
@interface ApiPageable {
}
Ce qui peut alors être utilisé comme suit:
@ApiPageable
public Page<Data> getData(Pageable pageRequest) {
La réponse de Vineet Bhatia aura un problème de validation lorsque tu ne cours pas sur localhost. Cela fera valoir pour les paramètres entiers qu'ils ne correspondent pas au schéma json.
J'ai donc changé de nombre entier en chaîne:
@ApiImplicitParams({
@ApiImplicitParam(name = "page", dataType = "string", paramType = "query",
value = "Results page you want to retrieve (0..N)"),
@ApiImplicitParam(name = "size", dataType = "string", paramType = "query",
value = "Number of records per page."),
@ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
value = "Sorting criteria in the format: property(,asc|desc). " +
"Default sort order is ascending. " +
"Multiple sort criteria are supported.")
})
Bien que la solution avec les paramètres implicites fonctionne, elle introduit beaucoup de code supplémentaire et fragile. Finalement nous sommes allés avec la solution suivante:
@GetMapping(value = "/")
public HttpEntity<PagedResources<Item>> getItems(
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size,
PagedResourcesAssembler assembler) {
Page<Item> itemPage = itemService.listItems(PageRequest.of(page, size, Sort.unsorted()));
return new ResponseEntity<>(assembler.toResource(itemPage), HttpStatus.OK);
}
Nous transmettons une PageRequest
(qui implémente Pageable
) à notre service, qui renvoie une Page
. (tous de org.springframework.data.domain
).
Le org.springframework.data.web.PagedResourcesAssembler
est injecté automatiquement par la méthode du contrôleur et permet de mapper des éléments sur org.springframework.hateoas.PagedResources
Nous n'avions pas besoin de tri dynamique, nous l'avons donc omis. Il est difficile d'ajouter un tri car springfox ne joue pas à Nice avec org.springframework.data.domain.Sort.