adn*_*n_e 4 spring-boot springfox spring-webflux
我正在使用 springfox 3.0.0 进行反应式支持,并@EnableSwagger2WebFlux在我的 swagger 配置中使用。
我的招摇配置如下:
@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage(basePackage))
            .paths(PathSelectors.any())
            .build()
            .securityContexts(Lists.newArrayList(securityContext()))
            .securitySchemes(Lists.newArrayList(apiKey()))
            .globalOperationParameters(operationParameters());
}
Run Code Online (Sandbox Code Playgroud)
我有一个简单的控制器,如下所示:
  @CrossOrigin(origins = "*", allowedHeaders = "*", maxAge = 3600)
  @RestController
  @RequestMapping("/")
  public class ApiController {
    @ApiOperation(value = "get all partners", authorizations = {@Authorization(value = "Bearer")})
    @RequestMapping(value = "/partner",
            method = RequestMethod.GET,
            produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
    )
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Request succeeded")
    })
    public Mono<ResponseEntity<Flux<PartnerDTO>>> getAllPartners(
            @ApiIgnore ServerHttpRequest httpRequest
    ) {
        return ...
    }
Run Code Online (Sandbox Code Playgroud)
我知道我可以通过在@ApiOperation 中指定响应类型来解决这个问题,但我试图避免这种情况,例如
@ApiOperation(value = "get all partners", authorizations = {@Authorization(value = "Bearer")})
@RequestMapping(value = "/partner",
        method = RequestMethod.GET,
        produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
)
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Request succeeded", response = PartnerDTO.class)
})
public Mono<ResponseEntity<Flux<PartnerDTO>>> getAllPartners(
        @ApiIgnore ServerHttpRequest httpRequest
) {
Run Code Online (Sandbox Code Playgroud)
我不喜欢这种方法,因为它是一个手动过程,因此容易出错。我想要一些自动方式来进行以下转换:
Flux<T> -> T[] (since flux emits 0...N elements)
Mono<T> -> T
ResponseEntity<T> -> T
Run Code Online (Sandbox Code Playgroud)
当然,它必须是递归的(例如Mono<ResponseEntity<Flux<T>>> -> T)。
我浏览了 springfox 的代码,试图找到一些自定义类型解析的入口点,幸运的是它有一个HandlerMethodResolver可以从外部注入的代码。
我在我的 swagger 配置类中添加了这个解析器的自定义实现:
@Bean
@Primary
public HandlerMethodResolver fluxMethodResolver(TypeResolver resolver) {
    return new HandlerMethodResolver(resolver) {
        @Override
        public ResolvedType methodReturnType(HandlerMethod handlerMethod) {
            var retType = super.methodReturnType(handlerMethod);
            // we unwrap Mono, Flux, and as a bonus - ResponseEntity
            while (
                    retType.getErasedType() == Mono.class
                    || retType.getErasedType() == Flux.class
                    || retType.getErasedType() == ResponseEntity.class
            ) {
                if ( retType.getErasedType() == Flux.class ) {
                    // treat it as an array
                    var type = retType.getTypeBindings().getBoundType(0);
                    retType = new ResolvedArrayType(type.getErasedType(), type.getTypeBindings(), type);
                } else {
                    retType = retType.getTypeBindings().getBoundType(0);
                }
            }
            return retType;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)
这正是我需要的。
它会自动转换Mono<ResponseEntity<Flux<PartnerDTO>>>到PartnerDTO[],并Mono<ResponseEntity<Mono<PartnerDTO>>>到PartnerDTO。
编辑::我更改了这个实现以将 Flux 转换为 T[],因为它从一开始就应该如此。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           2047 次  |  
        
|   最近记录:  |