我正在使用Kotlin和Sping Boot 3编写一个小应用程序。我希望有一个很好的异常处理,所以我创建了一个用@RestControllerAdvice
注解的类,有几个用@ExceptionHandler
注解的方法。我创建了一个data class
来存储返回的主体数据:
data class ApiError(
private val requestUri: String? = null,
private val status: Int = 0,
private val statusText: String? = null,
private val createdAt: ZonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Warsaw")),
private val errorMessage: String? = null,
)
剩下的就很简单了:
@RestControllerAdvice
class ControllerExceptionHandler {
@ExceptionHandler(HttpRequestMethodNotSupportedException::class)
fun methodNotSupportedException(
exception: HttpRequestMethodNotSupportedException,
request: HttpServletRequest,
): ResponseEntity<ApiError> {
println(buildApiError(request, HttpStatus.METHOD_NOT_ALLOWED, exception))
return ResponseEntity(
buildApiError(request, HttpStatus.METHOD_NOT_ALLOWED, exception),
HttpStatus.METHOD_NOT_ALLOWED,
)
}
@ExceptionHandler(NotFoundException::class)
fun notFoundExceptionHandler(
exception: NotFoundException,
request: HttpServletRequest,
): ResponseEntity<ApiError> {
println(buildApiError(request, HttpStatus.NOT_FOUND, exception))
return ResponseEntity(
buildApiError(request, HttpStatus.NOT_FOUND, exception),
HttpStatus.NOT_FOUND,
)
}
private fun buildApiError(
request: HttpServletRequest,
httpStatus: HttpStatus,
throwable: Throwable,
): ApiError {
return ApiError(
requestUri = request.requestURI,
status = httpStatus.value(),
statusText = httpStatus.reasonPhrase,
errorMessage = throwable.message,
)
}
}
而且还有这个(不要担心这个代码的质量,它只是为了测试的目的。
@RestController
@RequestMapping(
path = ["/hello"],
)
class HelloController {
@GetMapping("/{name}", produces = [MediaType.APPLICATION_JSON_VALUE])
private fun hello(@PathVariable name: String): ResponseEntity<Map<String, String>> {
// this is a forced exception so the @ExceptionHandlers could handle them.
if (name.lowercase() == "stefan") throw NotFoundException("Name not found!")
return ResponseEntity.ok(mapOf("Hello" to "$name!"))
}
}
问题是,当我运行应用程序并向'http://localhost:8080/hello/myrealname发送一个GET
请求时,我只收到一个很小的对象:
{
"Hello": "myrealname"
}
但是,当我POST到这个端点或使用名称“stefan”进行GET以触发异常时,我收到了一个正确的状态代码500或404,但是响应的主体是空的!
后来我试着返回一个字符串或者一个Map来代替我的ApiError
类,一切都很好,主体在那里,要么是Map要么是字符串。但是当我想返回ApiError
的一个示例时,主体是空的。裸'{}'
。我的对象有什么问题吗?这不是我第一次在控制器通知类中处理异常,我从来没有遇到过这样的情况。
这个问题的可能原因是什么?有没有更好的,更像Kotlin的方法来解决这个问题?有没有我不知道的扩展方法?
真诚的感谢你的任何线索:)
1条答案
按热度按时间gdx19jrr1#
由于您将
ApiError
数据类中的所有属性都定义为private,因此这些属性对于包含在spring-web中的JacksonObjectMapper序列化程序不可见。因此,要解决您的问题,您只需 * 删除privatemodifier*,如下所示: