You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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对象,核心原因包括:

  1. 父类BaseDto配置缺失:DataCenterDto继承自BaseDto,若BaseDto未提供无参构造、getter/setter(或未用@Data等注解),Jackson无法解析请求体中的父类字段(如id、createdAt),导致反序列化失败,生成空的DataCenterDto实例。
  2. 未开启参数校验:控制器方法的@RequestBody参数未加@Valid/@Validated注解,导致DataCenterDto中的@NotBlank校验未生效,且反序列化失败时无法抛出明确异常,无法定位问题。
  3. Jackson依赖异常:若项目未正确引入Jackson依赖(Spring Boot Starter Web默认集成,但手动管理依赖时可能缺失),会导致JSON反序列化失败。

解决方案

  1. 修复BaseDto配置:
    • 给BaseDto添加@Data注解,自动生成getter/setter和无参构造;若无法使用@Data,则手动实现这些方法,确保Jackson能解析父类字段。
  2. 开启参数校验:
    • 修改控制器方法,在@RequestBody前添加@Valid注解,触发JSR380校验,同时在反序列化失败时抛出明确异常:
      public ResponseEntity<OperationStatus> createDataCenter(@Valid @RequestBody DataCenterDto dataCenterDto) {
      
  3. 验证Jackson依赖:
    • 确保项目包含spring-boot-starter-web依赖(默认集成Jackson);若手动引入,确认com.fasterxml.jackson.core:jackson-databind已添加到依赖文件中。
  4. 简化请求体测试:
    • 暂时移除请求体中不必要的字段(如id、createdAt),仅保留name等核心字段,排除其他字段的反序列化干扰。
  5. 捕获反序列化异常:
    • 添加全局异常处理器,捕获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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:25:54