Spring Boot创建实体传name仍报‘Name cannot be blank’错误排查
问题:Spring Boot REST API 创建DataCenter时,请求体含name字段却仍报“Name cannot be blank”错误
开发Spring Boot应用时,通过REST API创建DataCenter,明明在请求体中提供了name字段,却持续收到“Name cannot be blank”错误,数据库中无数据生成。
相关代码
1. DataCenterRestApi控制器代码
@Slf4j @RestController @RequiredArgsConstructor @RequestMapping(AdminConstants.API_V1_DATA_CENTER_ROOT_URL) public class DataCenterRestApi { /** * Create data center. if user is not admin, it will be rejected. * * @param dataCenterDto data center dto * @return if the operation is success */ @Loggable @PreAuthorize(AUTHORIZE + " and hasRole('ADMIN')") @PostMapping public ResponseEntity<OperationStatus> createDataCenter(@RequestBody DataCenterDto dataCenterDto) { // Log incoming data Logger.getLogger(DataCenterRestApi.class.getName()) .info("Creating data center: " + dataCenterDto); if (Objects.isNull(dataCenterDto.getName())) { throw new IllegalArgumentException("Name cannot be blank"); } dataCenterService.createDataCenter(dataCenterDto); return ResponseEntity.ok(OperationStatus.SUCCESS); } }
2. DataCenterDto类代码
@Data @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = true) public class DataCenterDto extends BaseDto implements Serializable { @Serial private static final long serialVersionUID = -6342630857637389028L; @EqualsAndHashCode.Include private String publicId; @EqualsAndHashCode.Include @NotBlank(message = DataCenterConstants.BLANK_NAME) private String name; @Email(message = DataCenterConstants.INVALID_EMAIL) private String email; private String phone; // Address-related fields private String country; private String city; private String district; private String address; private String postalCode; // Other details private String description; private String ownerCompany; // Location-related fields @DecimalMin(value = DataCenterConstants.LATITUDE_MIN, message = DataCenterConstants.LATITUDE_RANGE) @DecimalMax(value = DataCenterConstants.LATITUDE_MAX, message = DataCenterConstants.LATITUDE_RANGE) private BigDecimal latitude; @DecimalMin(value = DataCenterConstants.LONGITUDE_MIN, message = DataCenterConstants.LONGITUDE_RANGE) @DecimalMax(value = DataCenterConstants.LONGITUDE_MAX, message = DataCenterConstants.LONGITUDE_RANGE) private BigDecimal longitude; // Activation status private boolean enabled; }
3. 发送的curl请求
curl -X 'POST' \ 'http://localhost:8080/api/v1/datacenter' \ -H 'accept: application/hal+json' \ -H 'Authorization: Bearer YOUR_TOKEN_HERE' \ -H 'Content-Type: application/json' \ -d '{ "id": 0, "version": 0, "createdAt": "2024-12-19T06:25:54.376Z", "createdBy": "string", "updatedAt": "2024-12-19T06:25:54.376Z", "updatedBy": "string", "publicId": "string", "name": "Test Data Center", "email": "test@gmail.com", "phone": "12345678901", "country": "Turkey", "city": "Istanbul", "district": "Besiktas", "address": "Test Address", "postalCode": "34020", "description": "Test Description", "ownerCompany": "Test Company", "latitude": 90, "longitude": 180, "enabled": true }'
错误信息及日志
收到的错误:
Name cannot be blank
日志输出:
2024-12-19T09:27:12.146+03:00 INFO 4016 --- [nio-8080-exec-2] c.ziyaret.annotation.impl.MethodLogger : => Starting - execution(DataCenterRestApi.createDataCenter(..)) args: [DataCenterDto(publicId=null, name=null, email=null, phone=null, country=null, city=null, district=null, address=null, postalCode=null, description=null, ownerCompany=null, latitude=null, longitude=null, enabled=false)] 2024-12-19T09:27:12.150+03:00 INFO 4016 --- [nio-8080-exec-2] c.ziyaret.web.rest.v1.DataCenterRestApi : Creating data center: DataCenterDto(publicId=null, name=null, email=null, phone=null, country=null, city=null, district=null, address=null, postalCode=null, description=null, ownerCompany=null, latitude=null, longitude=null, enabled=false) 2024-12-19T09:27:12.152+03:00 WARN 4016 --- [nio-8080-exec-2] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [java.lang.IllegalArgumentException: Name cannot be blank]
问题原因及解决方案
原因分析
从日志可见,传入的DataCenterDto所有字段均为null,说明请求体未被正确反序列化为DataCenterDto对象,核心原因包括:
- 父类
BaseDto配置缺失:DataCenterDto继承自BaseDto,若BaseDto未提供无参构造、getter/setter(或未用@Data等注解),Jackson无法解析请求体中的父类字段(如id、createdAt),导致反序列化失败,生成空的DataCenterDto实例。 - 未开启参数校验:控制器方法的
@RequestBody参数未加@Valid/@Validated注解,导致DataCenterDto中的@NotBlank校验未生效,且反序列化失败时无法抛出明确异常,无法定位问题。 - Jackson依赖异常:若项目未正确引入Jackson依赖(Spring Boot Starter Web默认集成,但手动管理依赖时可能缺失),会导致JSON反序列化失败。
解决方案
- 修复
BaseDto配置:- 给
BaseDto添加@Data注解,自动生成getter/setter和无参构造;若无法使用@Data,则手动实现这些方法,确保Jackson能解析父类字段。
- 给
- 开启参数校验:
- 修改控制器方法,在
@RequestBody前添加@Valid注解,触发JSR380校验,同时在反序列化失败时抛出明确异常:public ResponseEntity<OperationStatus> createDataCenter(@Valid @RequestBody DataCenterDto dataCenterDto) {
- 修改控制器方法,在
- 验证Jackson依赖:
- 确保项目包含
spring-boot-starter-web依赖(默认集成Jackson);若手动引入,确认com.fasterxml.jackson.core:jackson-databind已添加到依赖文件中。
- 确保项目包含
- 简化请求体测试:
- 暂时移除请求体中不必要的字段(如
id、createdAt),仅保留name等核心字段,排除其他字段的反序列化干扰。
- 暂时移除请求体中不必要的字段(如
- 捕获反序列化异常:
- 添加全局异常处理器,捕获
HttpMessageNotReadableException,打印详细错误信息:@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity<String> handleHttpMessageNotReadable(HttpMessageNotReadableException ex) { return ResponseEntity.badRequest().body("请求体解析失败: " + ex.getLocalizedMessage()); } }
- 添加全局异常处理器,捕获
内容的提问来源于stack exchange,提问作者Yunus Emre Alpu
相关产品推荐
相关产品推荐

