知識庫 / Spring / Spring MVC RSS 訂閱

Spring應用中不支持的媒體類型

Spring MVC
HongKong
7
12:23 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將演示 HTTP 響應代碼 415 “不支持的媒體類型” 在 Spring 應用中的 POST 請求的成因和解決方案。

2. 背景故事

一位老客户要求我們為其產品設計並開發一個新的桌面應用程序,用於管理用户。我們此前從未接觸過該產品。

由於時間緊迫,我們決定使用客户已有的後端API,該API在一段時間前就已經編寫完成。 我們面臨的挑戰在於,這些API的文檔並不詳盡。 因此,我們只確定了可用的API端點及其方法。我們決定不修改服務本身,而是專注於構建將從該服務中消費API的應用程序。

3. API 請求

我們的應用程序已經開始消耗 API。讓我們通過 API 獲取所有用户:

curl -X GET https://baeldung.service.com/user

歡呼!API 已成功響應。接下來,我們請求一個單獨的用户:

curl -X GET https://baeldung.service.com/user/{user-id}

讓我們檢查一下響應:

{
    "id": 1,
    "name": "Jason",
    "age": 23,
    "address": "14th Street"
}

這似乎也正常工作。因此,一切進展順利。根據響應,我們瞭解到用户具有以下參數:id, name, age, 和 address

現在,讓我們嘗試添加一個新用户:

curl -X POST -d '{"name":"Abdullah", "age":28, "address":"Apartment 2201"}' https://baeldung.service.com/user/

結果,我們收到一個帶有 HTTP 狀態碼 415 的錯誤響應:

{
    "timestamp": "yyyy-MM-ddThh:mm:ss.SSS+00:00",
    "status": 415,
    "error": "Unsupported Media Type",
    "path": "/user/"
}

在確定“我們為什麼會收到這個錯誤?”之前,我們需要先了解“這個錯誤是什麼?”。

4. 狀態碼 415:不支持的媒體類型

根據規範 RFC 7231 第 6.5.13 節 HTTP/1.1 語義和內容

415 (不支持的媒體類型) 狀態碼錶明源服務器拒絕處理請求,因為該負載格式未由目標資源的該方法所支持。

正如規範所建議的,我們選擇的媒體類型未被 API 支持。 選擇 JSON 作為媒體類型的原因是由於 GET 請求的響應。響應數據格式為 JSON。因此,我們假設 POST 請求也會接受 JSON。然而,這一假設證明是錯誤的。

為了確定 API 支持的格式,我們決定深入研究服務器端後端代碼,並找到 API 定義:

@PostMapping(value = "/", consumes = {"application/xml"})
void AddUser(@RequestBody User user)

這清楚地表明 API 只支持 XML 格式。 可能會有人疑問:Spring 中 “consumes” 元素有什麼作用?

根據 Spring 框架 文檔, “consumes” 元素的用途是:

通過媒體類型縮小主映射範圍,該媒體類型必須被映射處理器的消費。 包含一個或多個媒體類型,其中必須與請求的 Content-Type 請求頭匹配。

5. 解決辦法

我們面臨着兩種解決問題的方法。第一種方法是根據服務器的期望更改請求報文格式。第二種方法是更新API請求,使其支持JSON格式。

5.1. 請求報負載體轉換為 XML

以下是第一個選項,即改為使用 XML 格式發送請求,而不是 JSON

curl -X POST -d '<user><name>Abdullah</name><age>28</age><address>Apartment 2201</address></user>' https://baeldung.service.com/user/

不幸的是,我們得到了與上述請求相同的結果。如果回憶一下,我們曾提出過關於 問題,即 API 中 “consumes” 元素的用途是什麼。這讓我們意識到 我們的一個請求頭(“Content-Type”)缺失了。讓我們發送請求,這次缺少該請求頭:

curl -X POST -H "Content-Type: application/xml" -d '<user><name>Abdullah</name><age>28</age><address>Apartment 2201</address></user>' https://baeldung.service.com/user/

這次,我們成功收到響應。但是,我們可能會遇到客户端應用程序無法以支持的格式發送請求的情況。在這種情況下,我們需要在服務器端進行修改,以實現一定的靈活性。

5.2. 更新服務器端 API

假設我們的客户決定允許我們更改後端服務。 上述第二種方案是更新 API 請求以開始接受 JSON 格式。 以下是我們可以採用的更新 API 請求的進一步方案:

最簡單粗暴的方案是直接在 API 中將 XML 格式替換為 JSON:

@PostMapping(value = "/", consumes = {"application/json"}) 
void AddUser(@RequestBody User user)

讓我們從客户端應用程序中以JSON格式再次發送請求:

curl -X POST -H "Content-Type: application/json" -d '{"name":"Abdullah", "age":28, "address":"Apartment 2201"} https://baeldung.service.com/user/'

響應將成功。然而,我們將會面臨一個情況,即所有現有的客户端,它們以 XML 格式發送請求,現在將開始收到 415 Unsupported Media Type 錯誤。

第二種,相對簡單一些的方案是允許請求報文中所有格式:

@PostMapping(value = "/", consumes = {"*/*"}) 
void AddUser(@RequestBody User user

根據JSON格式的要求,響應將是成功的。然而,問題在於它過於靈活。我們不希望允許多種格式。這會導致代碼庫(包括客户端和服務器端)的行為不一致。

第三種且推薦的方案是添加客户端應用程序當前正在使用的特定格式。由於API已經支持XML格式,我們將保持其使用,因為已經有客户端應用程序將XML發送到API。為了使API支持我們的應用程序格式,我們將進行一個簡單的API代碼更改:

@PostMapping(value = "/", consumes = {"application/xml","application/json"}) 
void AddUser(@RequestBody User user

在將請求發送到JSON格式後,響應將成功。在特定場景中,這被認為是推薦的方法。

6. 結論

在本文中,我們瞭解到為了避免“Content-Type”請求頭在客户端應用程序中發送,必須避免415 Unsupported Media Type錯誤。 此外,RFC 明確指出,為了在發送POST請求時避免此錯誤,客户端應用程序和服務器端應用程序的“Content-Type”請求頭必須保持一致。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.