如何在Spring Doc中全局自定义Either响应类的处理逻辑?
解决方案
要实现Spring Doc全局自动解析Arrow-Kt Either<L, R>类型,只展示Right分支作为成功响应,无需逐个添加@ApiResponse,可以通过扩展Spring Doc的自定义组件实现,核心思路是拦截响应类型解析,将Either的泛型参数Right分支提取为实际响应类型。
1. 自定义OperationCustomizer处理响应类型
创建实现OperationCustomizer的类,遍历接口的响应定义,识别Either类型并替换为其Right分支的泛型类型:
import arrow.core.Either import io.swagger.v3.core.converter.ModelConverters import io.swagger.v3.oas.models.Operation import io.swagger.v3.oas.models.media.MediaType import io.swagger.v3.oas.models.media.Schema import org.springdoc.core.customizers.OperationCustomizer import org.springdoc.core.providers.RequestBuilder import org.springframework.stereotype.Component import java.lang.reflect.ParameterizedType import java.lang.reflect.Type @Component class EitherOperationCustomizer( private val requestBuilder: RequestBuilder, private val modelConverters: ModelConverters ) : OperationCustomizer { override fun customize(operation: Operation, handlerMethod: org.springframework.web.method.HandlerMethod): Operation { // 遍历所有响应,处理成功响应(默认200) operation.responses.values.forEach { apiResponse -> apiResponse.content?.values?.forEach { mediaType -> val schema = mediaType.schema ?: return@forEach // 检查当前schema是否对应Either类型 if (isEitherType(schema.implementation)) { val rightType = extractRightType(schema.implementation as ParameterizedType) // 生成Right类型的Schema val rightSchema = modelConverters.readAll(rightType).values.firstOrNull() rightSchema?.let { mediaType.schema = it } } } } return operation } private fun isEitherType(type: Class<*>?): Boolean { return type != null && Either::class.java.isAssignableFrom(type) } private fun extractRightType(parameterizedType: ParameterizedType): Type { // Either<L, R>的第二个泛型参数是Right分支 return parameterizedType.actualTypeArguments[1] } }
2. 自定义SchemaCustomizer(可选,优化全局Schema定义)
如果需要确保全局Schema中不生成Either类型的冗余定义,可以添加SchemaCustomizer过滤掉Either的Schema:
import arrow.core.Either import io.swagger.v3.oas.models.media.Schema import org.springdoc.core.customizers.SchemaCustomizer import org.springframework.stereotype.Component @Component class EitherSchemaCustomizer : SchemaCustomizer { override fun customize(schema: Schema<*>?, type: Class<*>?, name: String?, context: MutableMap<String, Any>?): Schema<*>? { // 如果当前类型是Either,返回null不生成对应的Schema return if (Either::class.java.isAssignableFrom(type)) null else schema } }
3. 验证效果
启动Spring应用后,访问Swagger UI(默认路径/swagger-ui.html),查看返回Either类型的接口:
- 成功响应(200)的模型会自动展示为Either的Right分支类型
- 无需在每个控制器方法上添加
@ApiResponse指定响应模型
关键说明
- 上述代码通过反射提取
Either<L, R>的第二个泛型参数作为响应类型,完全适配Arrow-Kt的Either结构 OperationCustomizer会拦截每个接口的OpenAPI定义,动态替换响应Schema- 如果需要在Swagger中展示Left分支对应的错误响应,可以在
customize方法中额外处理4xx/5xx响应,将Left分支类型作为错误响应模型
内容的提问来源于stack exchange,提问作者craigmiller160
相关产品推荐
相关产品推荐

