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”
。
然后,我们讨论了如何产生异常以及如何在实践中解决该异常。
0 评论