首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

SpringMVC 接收 JSON 日期參數 400 錯誤:@InitBinder 不生效的真兇——Getter/Setter 序列化註解不匹配

     編輯:程式設計疑難解答

問題現象

SpringMVC 接收包含 Date 字段的 JSON 請求,嘗試 Converter、@InitBinder、@DateTimeFormat 等多種方案均報 400 Bad Request。

根本原因

實體類中 Date 字段的 Getter 方法上有序列化註解(如 @JsonFormat),但 Setter 方法上缺少反序列化註解,導致 Jackson 反序列化失敗,請求甚至未進入 Controller,@InitBinder 自然不生效。

錯誤代碼示例

public class MyEntity {
    private Date createTime;
    
    // ❌ 只有 Getter 有註解,Setter 沒有
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    public Date getCreateTime() {
        return createTime;
    }
    
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

正確修復

方案一:在字段上統一註解(推薦,最簡潔)

public class MyEntity {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    
    public Date getCreateTime() { return createTime; }
    public void setCreateTime(Date createTime) { this.createTime = createTime; }
}

方案二:Getter/Setter 都加註解

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
public Date getCreateTime() { return createTime; }

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
public void setCreateTime(Date createTime) { this.createTime = createTime; }

方案三:全局配置 ObjectMapper(Spring Boot)

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        // 禁用將日期序列化為 timestamp
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        return mapper;
    }
}

為什麼 @InitBinder 不生效?

  1. SpringMVC 請求處理流程:HttpMessageConverter (Jackson) 反序列化 → 數據綁綁 → @InitBinder → Controller
  2. Jackson 反序列化階段失敗(400),請求直接終止,不進入後續綁定階段
  3. @InitBinder 是 WebDataBinder 階段處理表單數據/路徑變量,不處理 JSON Body 反序列化

調試技巧

// 開啟 Jackson 詳細錯誤日誌
logging.level.com.fasterxml.jackson.databind=DEBUG

// 或捕獲 HttpMessageNotReadableException 全局異常處理
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public Result handleJsonParseError(HttpMessageNotReadableException e) {
        log.error("JSON 解析失敗", e);
        return Result.error("JSON 格式錯誤: " + e.getMostSpecificCause().getMessage());
    }
}

總結

  • ✅ **字段級註解** 同時生效於序列化/反序列化,最省事
  • ✅ **全局 ObjectMapper** 統一日期格式,避免分散註解
  • ❌ **@InitBinder 不處理 JSON Body**,別在這條路上走彎路
  • 🔍 **400 錯誤看 Jackson 異常**,而非 SpringMVC 綁定異常
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved