知識庫 / Spring / Spring Web RSS 訂閱

HttpMessageNotWritableException: 無法找到適用於 [類 …] 的轉換器,且預設內容類型未設置

Spring Web
HongKong
5
12:21 PM · Dec 06 ,2025

1. 概述

在本文中,我們將深入探討 Spring 異常,即“HttpMessageNotWritableException: no converter for [class …] with preset Content-Type”。

首先,我們將揭示導致該異常的主要原因。然後,我們將深入研究,通過一個實際示例來重現該異常,最後,我們將探討如何解決它。

2. 原因

在深入瞭解細節之前,讓我們先嚐試理解這個異常的含義。

異常的堆棧跟蹤説明了一切:它告訴我們 Spring 無法找到能夠將 Java 對象轉換為 HTTP 響應的合適 HttpMessageConverter

基本上,Spring 依賴於 “Accept” 標頭來檢測它需要響應的媒體類型。

因此,使用沒有預註冊的消息轉換器,會導致 Spring 出現異常。

3. 重新觸發異常

現在我們知道導致 Spring 拋出我們自定義異常的原因,接下來讓我們通過一個實際示例來演示如何重現它。

讓我們創建一個處理方法,並假定指定一個沒有註冊的 HttpMessageConverter 的響應媒體類型。

例如,我們可以使用 APPLICATION_XML_VALUE“application/xml”

@GetMapping(value = "/student/v3/{id}", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Student> getV3(@PathVariable("id") int id) {
    return ResponseEntity.ok(new Student(id, "Robert", "Miller", "BB"));
}

接下來,我們向 http://localhost:8080/api/student/v3/1 發送一個請求,看看會發生什麼:

curl http://localhost:8080/api/student/v3/1

端點返回以下響應:

{"timestamp":"2022-02-01T18:23:37.490+00:00","status":500,"error":"Internal Server Error","path":"/api/student/v3/1"}

確實,查看日誌時,Spring 拋出了 HttpMessageNotWritableException 異常:

[org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.baeldung.boot.noconverterfound.model.Student] with preset Content-Type 'null']

因此,異常拋出是因為缺少能夠將 HttpMessageConverter 對象序列化和反序列化為 XML 中的 Student 對象的功能

最後,讓我們創建一個測試用例,以確認 Spring 會使用指定的消息拋出 HttpMessageNotWritableException

@Test
public void whenConverterNotFound_thenThrowException() throws Exception {
    String url = "/api/student/v3/1";

    this.mockMvc.perform(get(url))
      .andExpect(status().isInternalServerError())
      .andExpect(result -> assertThat(result.getResolvedException()).isInstanceOf(HttpMessageNotWritableException.class))
      .andExpect(result -> assertThat(result.getResolvedException()
        .getMessage()).contains("No converter for [class com.baeldung.boot.noconverterfound.model.Student] with preset Content-Type"));
}

4. 解決方案

解決異常的唯一方法是使用具有註冊的消息轉換器的媒體類型。

Spring Boot 依賴於自動配置來註冊內置的消息轉換器。

例如,如果 classpath 中包含 Jackson 2 依賴項,它將 自動註冊 MappingJackson2HttpMessageConverter

鑑於此,並且知道 Spring Boot 在 web starter 中包含 Jackson,讓我們創建一個新的端點,使用 APPLICATION_JSON_VALUE 媒體類型:

@GetMapping(value = "/student/v2/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Student> getV2(@PathVariable("id") int id) {
    return ResponseEntity.ok(new Student(id, "Kevin", "Cruyff", "AA"));
}

現在,讓我們創建一個測試用例,以確認一切都按預期工作:

@Test
public void whenJsonConverterIsFound_thenReturnResponse() throws Exception {
    String url = "/api/student/v2/1";

    this.mockMvc.perform(get(url))
      .andExpect(status().isOk())
      .andExpect(content().json("{'id':1,'firstName':'Kevin','lastName':'Cruyff', 'grade':'AA'}"));
}

如我們所見,Spring 不會拋出 HttpMessageNotWritableException,這要歸功於 MappingJackson2HttpMessageConverter,它在底層將 Student 對象轉換為 JSON。

5. 結論

在本簡短教程中,我們詳細討論了導致 Spring 拋出 <em “HttpMessageNotWritableException No converter for [class …] with preset Content-Type” 的原因。

在過程中,我們展示瞭如何製造該異常以及如何在實踐中修復它。

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

發佈 評論

Some HTML is okay.