提问者:小点点

Spring WebClient-如何处理身体Rest的错误


我是一个穿Spring靴的新手,我需要你的帮助。

我使用WebClient发出GET请求,我收到一个JSON正文,如下所示:

{
    "status": "OK",
    "error": [],
    "payload": {
        "name": "John",
        "surname": "Doe"
...
    }
}

所以我有一个DTO类,其中映射响应。类似于这样:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseAccountDTO {
    
    private String status;
    private List<ErrorDTO> errors;
    private User payload;

}

我使用以下方法:

public ResponseUserDTO retrieveUserById(String userId) {
    return webClient.get()
        .uri(GET_USER_BY_ID_V4, accountId)
        .header("Auth-Schema", AUTH_SCHEMA)
        .header("apikey", API_KEY)
        .accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .onStatus(HttpStatus::is4xxClientError, response -> {
            System.out.println("4xx error");
            return Mono.error(new RuntimeException("4xx"));
        })
        .onStatus(HttpStatus::is5xxServerError, response -> {
            System.out.println("5xx error");
            return Mono.error(new RuntimeException("5xx"));
        })
        .bodyToMono(ResponseDTO.class)
        .block();
}

最后,我用这种方法进行了测试:

UserRestClient userRestClient = new UserRestClient(webClient);

@Test
void retrieveUser() {
    ResponseDTO response = userRestClient.retrieveUserById("123");
    UserDTO user = response.getPayload();
    System.out.println("user surname: " + user.surname);
    assertEquals("Doe", user.getSurname());
}

在响应具有KO状态之前一切正常。如果出现问题(即坏请求),我会收到相同的正文JSON结构,如下所示:

{
    "status": "KO",
    "errors": [
        {
            "code": "ER000",
            "description": "Wrong ID parameter",
            "params": ""
        }
    ],
    "payload": {}
}

有没有办法在我的DTO类上也用KO状态映射JSON主体?我想返回retrieveUser()方法的错误描述。

更新:根据Seelenvirtuose的建议,我将错误添加到类中

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErrorDTO {
    
    private String code;
    private String description;
    private String params;

} 

共1个答案

匿名用户

我自己遇到了这个问题,必须将json错误响应转换为ErrorDTO对象。

希望下面的代码能帮助你找到你想要的。

下面的代码可以应用于任何状态代码(例如4xx、5xx甚至2xx,但2xx您不需要它)

.onStatus(HttpStatus::is4xxClientError, error -> error
  .bodyToMono(Map.class)
  .flatMap(body -> {      
     try {
         var message = objectMapper.writeValueAsString(body);
         ErrorDTO errorResponse = objectMapper.readValue(message, ErrorDTO.class);
         return Mono.error(new ServiceException(error.statusCode().value(), "My custom error message",                                                         errorResponse));
     } catch (JsonProcessingException jsonProcessingException) {
         return Mono.error(new ServiceException("Cannot parse the error response"));
     }
  })
)