動態

詳情 返回 返回

SpringBoot解決406錯誤之返回對象缺少Getter/Setter方法引發的問題 - 動態 詳情

問題背景

在本地環境下,我們以POST方式向Spring Boot應用發起請求,這是一個查詢部門信息的地址。

請求信息:http://localhost:8080/depts

當使用接口測試工具進行接口測試後,報錯如下:

{
    "timestamp": "2025-04-13T10:46:20.933+00:00",
    "status": 406,
    "error": "Not Acceptable",
    "path": "/depts"
}

從錯誤信息中可以看到返回狀態碼為406 Not Acceptable,這表明服務器無法根據請求的內容協商出合適的響應格式,因而返回了錯誤信息。這一問題通常是由於請求與響應的數據格式或返回對象的序列化問題導致的。接下來我們詳細分析該問題的具體原因。

問題分析

在Spring Boot中,406 Not Acceptable錯誤通常表示服務器找不到與請求Accept頭匹配的數據格式,而Accept頭指明瞭客户端希望接受的數據類型(如JSON、XML等)。在我們的例子中,雖然請求沒有明確指定Accept頭,Spring Boot會默認將返回值序列化為JSON格式。因此,問題很可能出在返回數據類型的格式化上。

我們在該請求的返回對象中,使用了自定義的Result類,用於封裝返回的狀態碼、消息及數據內容,其結構大致如下:

public class Result {
    private Integer code;
    private String msg;
    private Object data;
}

通過Result類返回封裝的信息,有助於我們在接口中統一返回格式。Result類中的code表示狀態碼,message包含提示信息,data字段存放返回的數據對象。然而,我們沒有為Result類的字段添加getter和setter方法。

在Spring Boot中,使用@RestController註解的控制器方法會默認嘗試將返回對象轉換為JSON格式。如果Result類缺少getter和setter方法,Spring Boot將無法讀取Result的屬性進行JSON序列化,從而引發406 Not Acceptable錯誤。

解決方法

添加getter和setter方法,或添加@Data註解:

@Data
public class Result {
    private Integer code;
    private String msg;
    private Object data;
}

通過添加getter和setter方法,Jackson可以正確地讀取和寫入Result對象中的字段,從而將其轉換為JSON格式返回給客户端。

接口測試

完成上述代碼修改後,再次使用POST方式調用http://localhost:8080/depts,此時返回的數據應為JSON格式:

{
    "code": 1,
    "msg": "success",
    "data": [
        {
            "id": 1104,
            "name": "生產部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1110,
            "name": "工程部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1103,
            "name": "公關部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1107,
            "name": "生產部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1105,
            "name": "法律部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1102,
            "name": "會計及金融部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1108,
            "name": "研究及開發部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1106,
            "name": "市場部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1109,
            "name": "產品質量部",
            "createdTime": null,
            "updatedTime": null
        },
        {
            "id": 1101,
            "name": "工程部",
            "createdTime": null,
            "updatedTime": null
        }
    ]
}

原理探討

Spring Boot中,@RestController註解標識的控制器方法默認返回JSON數據,這依賴於Spring的消息轉換器(HttpMessageConverters)。Spring Boot內置了Jackson庫作為JSON的默認轉換工具。若返回的對象不具備getter和setter方法,Jackson將無法訪問其屬性,導致序列化失敗,從而引發406 Not Acceptable異常。

在設計API返回對象時,建議始終遵循JavaBean的規範,為屬性添加getter和setter方法,並確保字段可訪問。這樣不僅可以提高程序的兼容性,還能更好地遵循RESTful API的設計規範,避免序列化問題。

常見問題&調優建議

除了返回對象缺少getter/setter方法外,還可能出現以下問題導致406 Not Acceptable異常:

請求頭不匹配:確保客户端的Accept頭和服務端返回的Content-Type匹配,如application/json。
序列化衝突:若返回對象包含複雜類型,建議將複雜對象轉換為簡單類型或DTO,以便於JSON轉換。
註解配置問題:在某些特殊需求下,可以通過@ResponseBody、@RequestMapping(produces="application/json")等註解控制返回類型。
此外,為了提高系統的健壯性和API接口的一致性,建議在項目中引入統一的響應處理機制。可以創建一個全局異常處理類,捕獲序列化問題或類型轉換問題,確保返回友好的錯誤信息,避免錯誤暴露給客户端。

Add a new 評論

Some HTML is okay.