HttpMessageNotWritableException:未找到類型返回值的轉換器
1.概述
在本教程中,我們將闡明Spring的HttpMessageNotWritableException: “No converter found for return value of type”
異常。
首先,我們將解釋導致異常的主要原因。然後,我們將進行更深入的研究,以了解如何使用實際示例來製作它,以及最後如何修復它。
2.原因
通常,當Spring無法獲取返回對象的屬性時,將發生此異常。
導致此異常的最典型原因通常是,返回的對象的屬性沒有任何公共的getter方法。
默認情況下,Spring Boot依靠Jackson庫來完成所有序列化/反序列化請求和響應對象的繁重工作。
因此,導致我們異常的另一個常見原因可能是缺少或使用了錯誤的Jackson依賴項。
簡而言之,此類例外的一般準則是檢查是否存在以下情況:
- 默認構造函數
- Getters方法
- Jackson依賴
請記住, 異常類型已從java.lang.IllegalArgumentException
更改為org.springframework.http.converter.HttpMessageNotWritableException.
3.實際例子
現在,讓我們看一個生成org.springframework.http.converter.HttpMessageNotWritableException
的示例:“未找到類型返回值的轉換器”。
為了演示真實的用例,我們將使用Spring Boot構建一個用於學生管理的基本REST API。
首先,讓我們創建模型類Student
並假裝忘記生成getter方法:
public class Student {
private int id;
private String firstName;
private String lastName;
private String grade;
public Student() {
}
public Student(int id, String firstName, String lastName, String grade) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.grade = grade;
}
// Setters
}
其次,我們將創建一個具有單個處理程序方法的Spring控制器,以按其id
Student
對象:
@RestController
@RequestMapping(value = "/api")
public class StudentRestController {
@GetMapping("/student/{id}")
public ResponseEntity<Student> get(@PathVariable("id") int id) {
// Custom logic
return ResponseEntity.ok(new Student(id, "John", "Wiliams", "AA"));
}
}
現在,如果我們使用CURL http://localhost:8080/api/student/1
curl http://localhost:8080/api/student/1
端點將發回此響應:
{"timestamp":"2021-02-14T14:54:19.426+00:00","status":500,"error":"Internal Server Error","message":"","path":"/api/student/1"}
查看日誌,Spring拋出了HttpMessageNotWritableException
:
[org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.baeldung.boot.noconverterfound.model.Student]
最後,讓我們創建一個測試用例,以查看未在Student
類中定義getter方法時Spring的行為:
@RunWith(SpringRunner.class)
@WebMvcTest(StudentRestController.class)
public class NoConverterFoundIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void whenGettersNotDefined_thenThrowException() throws Exception {
String url = "/api/student/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 found for return value of type"));
}
}
4.解決方案
防止異常的最常見解決方案之一是為我們要以JSON返回的每個對象的屬性定義一個getter方法。
因此,讓我們在Student
類中添加getter方法並創建一個新的測試用例,以驗證一切是否都能按預期工作:
@Test
public void whenGettersAreDefined_thenReturnObject() throws Exception {
String url = "/api/student/2";
this.mockMvc.perform(get(url))
.andExpect(status().isOk())
.andExpect(jsonPath("$.firstName").value("John"));
}
一個不明智的解決方案是將這些物業公開。但是,這不是100%安全的方法,因為它違反了一些最佳實踐。
5.結論
在這篇簡短的文章中,我們解釋了導致Spring拋出org.springframework.http.converter.HttpMessageNotWritableException: ” No converter found for return value of type”
。
然後,我們討論瞭如何產生異常以及如何在實踐中解決該異常。