我使用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生成独立的查询参数字段?
请注意我使用的是带有Gradle的Springfox:
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'
答案 0 :(得分:24)
这是Spring-Fox的一个已知问题。请参阅问题#755。根据zdila的评论2,此时替代方法是添加@ApiImplicitParams,这不是理想的但它确实有效。
Process p = Runtime.getRuntime().exec("execution.exe --login user");
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(p.getOutputStream()));
writer.write("mypassword\n");
writer.flush();
writer.close();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("System returns message:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("System returns error message:\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
[
1 https://github.com/springfox/springfox/issues/755
2 https://github.com/springfox/springfox/issues/755#issuecomment-135059871
答案 1 :(得分:7)
在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) {
答案 2 :(得分:5)
Vineet Bhatia对@ApiImplicitParams
的回答看起来不错。但是我遇到了情况,当@ApiIgnor
和@ApiParam(hidden = true)
不起作用时,您仍然可以观察到整体和可分页的参数。我通过添加下一行
docket.ignoredParameterTypes(Pageable.class, PagedResourcesAssembler.class);
到我的SwaggerConfig
中的Docket bean。
答案 3 :(得分:2)
如果您没有在localhost上运行,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.")
})
答案 4 :(得分:2)
这是已集成到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 {
}
答案 5 :(得分:1)
对于希望在2019年解决此问题的人。通过springfox documentation进行的此配置可以很好地工作,除非您无法设置参数说明。
代码在这里。
答案 6 :(得分:0)
尽管使用隐式参数的解决方案有效,但它引入了许多额外的易碎代码。最后,我们采用了以下解决方案:
@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
)传递给我们的服务,该服务返回一个Page
。 (全部来自org.springframework.data.domain
)。
org.springframework.data.web.PagedResourcesAssembler
通过控制器方法自动注入,并允许将项目映射到org.springframework.hateoas.PagedResources
我们不需要动态排序,因此我们省略了它;由于springfox无法与org.springframework.data.domain.Sort配合使用,因此添加排序带来了一些挑战。
答案 7 :(得分:0)
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.") })
答案 8 :(得分:0)
此解决方案无需注释每个控制器中的每个API方法即可工作。首先,我们用正确的属性名称和描述({Kotlin代码,您可以使用Java接口)来创建Pageable
类的替换:
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
的直接替代项添加到此类(同样是Kotlin代码,但是Java应该非常相似):
@Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Pageable::class.java, SwaggerPageable::class.java)
}
结果如下:
缺点是无法在ApiModelProperty
中定义默认值,但这对于我的项目已经足够了。
答案 9 :(得分:0)
Java示例:
Bean:
@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;
}
大摇大摆:
答案 10 :(得分:0)
Open 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)