Spring Rest Controller用HttpEntity接收请求,Swagger测试时Body为Null
问题原因
Spring MVC 可以自动将请求的头信息和请求体封装到 HttpEntity 参数中,但 springdoc-openapi-ui 默认不会识别 HttpEntity 泛型中的实体类作为接口的请求体。这就导致 Swagger UI 不会生成对应的请求体输入区域,测试时无法传递请求体,最终 httpEntity.getBody() 返回 null。
解决方案
以下两种方案无需大范围修改现有接口,可快速解决问题:
方案一:为 HttpEntity 参数添加 @RequestBody 注解
直接在控制器方法的 HttpEntity 参数上添加 OpenAPI 的 @RequestBody 注解,明确指定请求体的 Schema。这样 Swagger UI 会自动生成请求体输入框,测试时就能正确传递请求体。
修改后的控制器方法代码:
@PostMapping(value = "/submit", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "API for submit", description = "Submit data") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(schema = @Schema(implementation = Failure.class))), @ApiResponse(responseCode = "500", description = "Error", content = @Content(schema = @Schema(implementation = Failure.class))), }) public ResponseEntity<Success<SubmitOpr>> submit( @RequestBody(description = "请求数据", content = @Content(schema = @Schema(implementation = OperationReq.class))) HttpEntity<OperationReq> httpEntity) throws Exception { log.info("Request Entity is {}", httpEntity); log.info("Request Body is {}", httpEntity.getBody()); SuccessResponse<SubmitOpr> response = null; try { response = oprService.submit(httpEntity); } catch (Exception e) { log.error("Failure: {}", e.getMessage()); throw e; } return ResponseEntity.ok().body(response); }
方案二:全局配置 OpenApiCustomizer 批量处理
如果同类接口数量较多,可通过自定义 OpenApiCustomizer 实现全局批量处理,自动为所有包含 HttpEntity 参数的接口添加请求体定义,无需逐个修改接口。
步骤1:编写自定义 OpenApiCustomizer
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import org.springdoc.core.customizers.OpenApiCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpEntity; import java.util.Iterator; @Configuration public class SpringDocConfig { @Bean public OpenApiCustomizer httpEntityRequestBodyCustomizer() { return openApi -> { openApi.getPaths().values().forEach(pathItem -> { pathItem.readOperations().forEach(operation -> { Iterator<Parameter> paramIterator = operation.getParameters().iterator(); while (paramIterator.hasNext()) { Parameter param = paramIterator.next(); // 判断参数是否为HttpEntity类型 if (param.getSchema().get$ref() != null && param.getSchema().get$ref().contains(HttpEntity.class.getSimpleName())) { // 替换为实际项目中HttpEntity的泛型类,若需适配多个类可通过反射解析泛型 Class<?> bodyClass = OperationReq.class; Schema<?> bodySchema = new Schema<>().$ref("#/components/schemas/" + bodyClass.getSimpleName()); // 构建请求体 RequestBody requestBody = new RequestBody() .content(new Content() .addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, new MediaType().schema(bodySchema))); operation.setRequestBody(requestBody); // 移除原HttpEntity参数(它并非URL参数,而是封装请求体和头的容器) paramIterator.remove(); } } }); }); }; } }
说明
- 若需要适配多个不同泛型的
HttpEntity,可通过反射获取控制器方法的参数类型,解析HttpEntity的泛型实际类型,替换示例中固定的OperationReq.class。 - 配置完成后,所有包含
HttpEntity参数的接口都会自动在 Swagger UI 中显示请求体输入区域。
内容的提问来源于stack exchange,提问作者iCode
相关产品推荐
相关产品推荐

