如何处理Rest模板api错误响应并转换为类型安全的Json?

sky*_*tor 1 java exception kotlin spring-boot

我是 Spring Boot 的新手,我想以类型安全的方式处理剩余模板中的错误响应。

我已经尝试过使用剩余模板进行异常处理,但它不能解决我的问题。或者也许我不知道如何正确使用它。

val restTemplate = RestTemplate() restTemplate.exchange(uri, HttpMethod.POST, payload, UserResponse::class.java) // getting error here because of error response

//我真正想要的是这样的

val restTemplate = RestTemplate() restTemplate.setSuccessEntity(UserResponse::class.java) restTemplate.setErrorEntity(ErrorResponse::class.java) restTemplate.exchange(uri, HttpMethod.POST, payload)

预期的反应是这样的

{ "error":{} // null or ErrorResponse Entity object if there is an error "success":{} // null or UserResponse Entity object if there is an error }

Mac*_*cki 5

  1. 定义您的定制RestTemplateResponseErrorHandler
class MyRestTemplateResponseErrorHandler : ResponseErrorHandler {
 override fun hasError(response: ClientHttpResponse): Boolean {
   return response.statusCode.is4xxClientError || response.statusCode.is5xxServerError //or sth else depending on your case
 }
 override fun handleError(response: ClientHttpResponse) {
   val msg = response.body.bufferedReader().use(BufferedReader::readText)
   throw MyExternalApiException(msg)
 }
}
Run Code Online (Sandbox Code Playgroud)

MyExternalApiException可以这样定义:

class MyExternalApiError(msg: String) : RuntimeException(msg)
Run Code Online (Sandbox Code Playgroud)
  1. 使其成为Bean
@Bean
fun responseErrorHandler(): ResponseErrorHandler {
  return MyRestTemplateResponseErrorHandler()
}
Run Code Online (Sandbox Code Playgroud)
  1. 用它来RestTemplate Bean创建RestTemplateBuilder
@Bean
fun restTemplate(restTemplateBuilder: RestTemplateBuilder,
                     responseErrorHandler: ResponseErrorHandler): RestTemplate {
        return restTemplateBuilder
                .errorHandler(responseErrorHandler)
                .build()
}
Run Code Online (Sandbox Code Playgroud)
  1. 现在您的错误处理程序可以正常工作并且MyExternalApiException在外部 api 失败时抛出异常,您可以创建ControllerAdvice在发生此异常时返回特殊实体。您的控制器将返回ErrorResponse您从失败的外部 api 请求中获得的消息。
@ControllerAdvice
class ApiErrorHandler {

  @ExceptionHandler(value = [MyExternalApiException::class])
  fun handleExternalApiException(e: MyExternalApiException): ResponseEntity<ErrorResponse> {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(ErrorResponse(e.message
                        ?: "External api error"))
    }

 data class ErrorResponse(val message: String)

Run Code Online (Sandbox Code Playgroud)

如果请求成功,只需正常返回您成功的实体即可。如果您想在所有响应中同时包含errorsuccess字段,只需设置其中一个字段即可。errorApiErrorHandlersuccess之后restTemplate.exchange().

如果您希望将该外部错误映射到您的类,而不是字符串,您可以使用 jacksons 对象映射器或其他库。