Spring 可分页界面的 Swagger 文档
Swagger documentation for Spring Pageable interface
我使用 Spring Boot 开发了一个微服务。 REST API 的文档是用 Swagger 制作的。一些 REST 资源利用 Spring 概念免费提供分页。下面是一个例子:
@RequestMapping(value = "/buckets", method = GET)
public PagedResources list(Pageable pageable, PagedResourcesAssembler assembler) {
return bucketService.listBuckets(pageable, assembler);
}
如果我打开 Swagger 页面,可以使用以下表格获取资源:
我遇到的问题是检测到内容类型为 application/json 的可分页参数,我不知道如何传递值来更改页面例如尺寸。所有值似乎都被忽略了。
是否可以将查询参数作为 JSON 对象传递?或者是否可以配置 Swagger 为 Pageable 接口包含的 getter 生成独立的查询参数字段?
请注意,我正在使用 Springfox 和 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'
这是 Spring-Fox 的一个已知问题。请参阅问题 #755. Based on zdila's comment 2,此时替代方法是添加 @ApiImplicitParams,这并不理想,但确实有效。
@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.")
})
[
1 https://github.com/springfox/springfox/issues/755
2 https://github.com/springfox/springfox/issues/755#issuecomment-135059871
Vineet Bhatia @ApiImplicitParams
的回答看起来不错。但是我遇到了这样的情况,当 @ApiIgnor
和 @ApiParam(hidden = true)
不起作用时,您仍然可以观察到 asembler 和 pageable 参数。我通过添加下一行
解决了这个问题
docket.ignoredParameterTypes(Pageable.class, PagedResourcesAssembler.class);
到我的 SwaggerConfig
中的 Docket bean。
当您不在 运行 本地主机上时,Vineet Bhatia 的回答将出现验证问题。它将争论整数参数,它们不对应于 json 模式。
所以我将整数更改为字符串:
@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.")
})
基于 Vineet Bhatia 的回答,您可以将解决方案包装在自定义注释中以实现可重用性:
@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 {
}
然后可以这样使用:
@ApiPageable
public Page<Data> getData(Pageable pageRequest) {
虽然使用隐式参数的解决方案有效,但它引入了很多额外的、脆弱的代码。最后我们采用了以下解决方案:
@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);
}
我们将 PageRequest
(实现 Pageable
)传递给我们的服务,returns Page
。 (全部来自 org.springframework.data.domain
)。
org.springframework.data.web.PagedResourcesAssembler
通过控制器方法自动注入并允许将项目映射到 org.springframework.hateoas.PagedResources
我们不需要动态排序,所以我们忽略了它;它对添加排序提出了一些挑战,因为 springfox 不能与 org.springframework.data.domain.Sort.
配合使用
对于想在 2019 年解决此问题的人。通过 springfox documentation 进行的此配置工作正常,但不能设置参数说明。
代码在这里。
Evgeny 指出的验证问题的答案。
正在使用
@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.") })
抛出异常:
Illegal DefaultValue for parameter type integer
java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Long.parseLong(Long.java:709)
at java.base/java.lang.Long.valueOf(Long.java:1151)
at io.swagger.models.parameters.AbstractSerializableParameter.getExample(AbstractSerializableParameter.java:412)
at jdk.internal.reflect.GeneratedMethodAccessor366.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
(至少,它适用于 springfox-swagger2 和 springfox-swagger2-ui 版本 2.9.2)
您可以按照 Evgeny 的回答或为整数参数添加默认值和示例值来避免异常:
@ApiImplicitParams({
@ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "Results page you want to retrieve (0..N)", defaultValue = "0", example = "2"),
@ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "Number of records per page.", defaultValue = "20", example = "10"),
@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.") })
此解决方案无需在每个控制器中注释每个 API 方法即可工作。首先,我们用正确的 属性 名称和描述创建 Pageable
class 的替换(Kotlin 代码,您可以使用 Java 的接口):
data class SwaggerPageable(
@ApiModelProperty("Number of records per page", example = "20")
val size: Int?,
@ApiModelProperty("Results page you want to retrieve (0..N)", example = "0")
val page: Int?,
@ApiModelProperty("Sorting criteria in the format: property(,asc|desc)." +
"Default sort order is ascending. Multiple sort criteria are supported.")
var sort: String?
)
然后在 Swagger 配置中,只需将 Pageable
的直接替代添加到此 class(同样是 Kotlin 代码,但 Java 应该非常相似):
@Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Pageable::class.java, SwaggerPageable::class.java)
}
结果如下所示:
缺点是无法在 ApiModelProperty
中定义默认值,但这对我的项目来说已经足够好了。
这是集成到 OpenAPI v3 的 springdoc-openapi-data-rest 中的注释版本:
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Parameter(in = ParameterIn.QUERY
, description = "Zero-based page index (0..N)"
, name = "page"
, content = @Content(schema = @Schema(type = "integer", defaultValue = "0")))
@Parameter(in = ParameterIn.QUERY
, description = "The size of the page to be returned"
, name = "size"
, content = @Content(schema = @Schema(type = "integer", defaultValue = "20")))
@Parameter(in = ParameterIn.QUERY
, description = "Sorting criteria in the format: property(,asc|desc). "
+ "Default sort order is ascending. " + "Multiple sort criteria are supported."
, name = "sort"
, content = @Content(array = @ArraySchema(schema = @Schema(type = "string"))))
public @interface PageableAsQueryParam {
}
Java 例子:
豆子:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Pageable.class, SwaggerPageable.class);
}
SwaggerPageable:
@Getter
private static class SwaggerPageable {
@ApiParam(value = "Number of records per page", example = "0")
@Nullable
private Integer size;
@ApiParam(value = "Results page you want to retrieve (0..N)", example = "0")
@Nullable
private Integer page;
@ApiParam(value = "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.")
@Nullable
private String sort;
}
大摇大摆:
开放 API 3.0 无缝集成。
例如,
@GetMapping("/filter")
public Page<Employee> filterEmployees(Pageable pageable) {
return repository.getEmployees(pageable);
}
添加springdoc-openapi-data-rest依赖
implementation 'org.springdoc:springdoc-openapi-data-rest:1.5.2'
注意:如果您有多个参数,您可以添加'@ParameterObject'
public Page<Employee> filterEmployees(@ParameterObject Pageable pageable)
这是 springdoc-openapi-ui
的解决方案
SpringDocUtils.getConfig()
.replaceWithClass(org.springframework.data.domain.Pageable.class, SwaggerPageable.class);
@Getter
private static class SwaggerPageable {
@ApiParam(value = "Number of records per page", example = "0")
@Nullable
private Integer size;
@ApiParam(value = "Results page you want to retrieve (0..N)", example = "0")
@Nullable
private Integer page;
@ApiParam(value = "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.")
@Nullable
private String sort;
}
我使用 Spring Boot 开发了一个微服务。 REST API 的文档是用 Swagger 制作的。一些 REST 资源利用 Spring 概念免费提供分页。下面是一个例子:
@RequestMapping(value = "/buckets", method = GET)
public PagedResources list(Pageable pageable, PagedResourcesAssembler assembler) {
return bucketService.listBuckets(pageable, assembler);
}
如果我打开 Swagger 页面,可以使用以下表格获取资源:
我遇到的问题是检测到内容类型为 application/json 的可分页参数,我不知道如何传递值来更改页面例如尺寸。所有值似乎都被忽略了。
是否可以将查询参数作为 JSON 对象传递?或者是否可以配置 Swagger 为 Pageable 接口包含的 getter 生成独立的查询参数字段?
请注意,我正在使用 Springfox 和 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'
这是 Spring-Fox 的一个已知问题。请参阅问题 #755. Based on zdila's comment 2,此时替代方法是添加 @ApiImplicitParams,这并不理想,但确实有效。
@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.")
})
[
1 https://github.com/springfox/springfox/issues/755
2 https://github.com/springfox/springfox/issues/755#issuecomment-135059871
Vineet Bhatia @ApiImplicitParams
的回答看起来不错。但是我遇到了这样的情况,当 @ApiIgnor
和 @ApiParam(hidden = true)
不起作用时,您仍然可以观察到 asembler 和 pageable 参数。我通过添加下一行
docket.ignoredParameterTypes(Pageable.class, PagedResourcesAssembler.class);
到我的 SwaggerConfig
中的 Docket bean。
当您不在 运行 本地主机上时,Vineet Bhatia 的回答将出现验证问题。它将争论整数参数,它们不对应于 json 模式。
所以我将整数更改为字符串:
@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.")
})
基于 Vineet Bhatia 的回答,您可以将解决方案包装在自定义注释中以实现可重用性:
@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 {
}
然后可以这样使用:
@ApiPageable
public Page<Data> getData(Pageable pageRequest) {
虽然使用隐式参数的解决方案有效,但它引入了很多额外的、脆弱的代码。最后我们采用了以下解决方案:
@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);
}
我们将 PageRequest
(实现 Pageable
)传递给我们的服务,returns Page
。 (全部来自 org.springframework.data.domain
)。
org.springframework.data.web.PagedResourcesAssembler
通过控制器方法自动注入并允许将项目映射到 org.springframework.hateoas.PagedResources
我们不需要动态排序,所以我们忽略了它;它对添加排序提出了一些挑战,因为 springfox 不能与 org.springframework.data.domain.Sort.
配合使用对于想在 2019 年解决此问题的人。通过 springfox documentation 进行的此配置工作正常,但不能设置参数说明。
代码在这里。
Evgeny 指出的验证问题的答案。
正在使用
@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.") })
抛出异常:
Illegal DefaultValue for parameter type integer
java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Long.parseLong(Long.java:709)
at java.base/java.lang.Long.valueOf(Long.java:1151)
at io.swagger.models.parameters.AbstractSerializableParameter.getExample(AbstractSerializableParameter.java:412)
at jdk.internal.reflect.GeneratedMethodAccessor366.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
(至少,它适用于 springfox-swagger2 和 springfox-swagger2-ui 版本 2.9.2)
您可以按照 Evgeny 的回答或为整数参数添加默认值和示例值来避免异常:
@ApiImplicitParams({
@ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "Results page you want to retrieve (0..N)", defaultValue = "0", example = "2"),
@ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "Number of records per page.", defaultValue = "20", example = "10"),
@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.") })
此解决方案无需在每个控制器中注释每个 API 方法即可工作。首先,我们用正确的 属性 名称和描述创建 Pageable
class 的替换(Kotlin 代码,您可以使用 Java 的接口):
data class SwaggerPageable(
@ApiModelProperty("Number of records per page", example = "20")
val size: Int?,
@ApiModelProperty("Results page you want to retrieve (0..N)", example = "0")
val page: Int?,
@ApiModelProperty("Sorting criteria in the format: property(,asc|desc)." +
"Default sort order is ascending. Multiple sort criteria are supported.")
var sort: String?
)
然后在 Swagger 配置中,只需将 Pageable
的直接替代添加到此 class(同样是 Kotlin 代码,但 Java 应该非常相似):
@Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Pageable::class.java, SwaggerPageable::class.java)
}
结果如下所示:
缺点是无法在 ApiModelProperty
中定义默认值,但这对我的项目来说已经足够好了。
这是集成到 OpenAPI v3 的 springdoc-openapi-data-rest 中的注释版本:
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Parameter(in = ParameterIn.QUERY
, description = "Zero-based page index (0..N)"
, name = "page"
, content = @Content(schema = @Schema(type = "integer", defaultValue = "0")))
@Parameter(in = ParameterIn.QUERY
, description = "The size of the page to be returned"
, name = "size"
, content = @Content(schema = @Schema(type = "integer", defaultValue = "20")))
@Parameter(in = ParameterIn.QUERY
, description = "Sorting criteria in the format: property(,asc|desc). "
+ "Default sort order is ascending. " + "Multiple sort criteria are supported."
, name = "sort"
, content = @Content(array = @ArraySchema(schema = @Schema(type = "string"))))
public @interface PageableAsQueryParam {
}
Java 例子:
豆子:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Pageable.class, SwaggerPageable.class);
}
SwaggerPageable:
@Getter
private static class SwaggerPageable {
@ApiParam(value = "Number of records per page", example = "0")
@Nullable
private Integer size;
@ApiParam(value = "Results page you want to retrieve (0..N)", example = "0")
@Nullable
private Integer page;
@ApiParam(value = "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.")
@Nullable
private String sort;
}
大摇大摆:
开放 API 3.0 无缝集成。
例如,
@GetMapping("/filter")
public Page<Employee> filterEmployees(Pageable pageable) {
return repository.getEmployees(pageable);
}
添加springdoc-openapi-data-rest依赖
implementation 'org.springdoc:springdoc-openapi-data-rest:1.5.2'
注意:如果您有多个参数,您可以添加'@ParameterObject'
public Page<Employee> filterEmployees(@ParameterObject Pageable pageable)
这是 springdoc-openapi-ui
的解决方案SpringDocUtils.getConfig()
.replaceWithClass(org.springframework.data.domain.Pageable.class, SwaggerPageable.class);
@Getter
private static class SwaggerPageable {
@ApiParam(value = "Number of records per page", example = "0")
@Nullable
private Integer size;
@ApiParam(value = "Results page you want to retrieve (0..N)", example = "0")
@Nullable
private Integer page;
@ApiParam(value = "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.")
@Nullable
private String sort;
}