[spring] Spring Resttemplate 예외 처리

다음은 코드 스 니펫입니다. 기본적으로 오류 코드가 200이 아닌 경우 예외를 전파하려고합니다.

ResponseEntity<Object> response = restTemplate.exchange(url.toString().replace("{version}", version),
                    HttpMethod.POST, entity, Object.class);
            if(response.getStatusCode().value()!= 200){
                logger.debug("Encountered Error while Calling API");
                throw new ApplicationException();
            }

그러나 서버에서 500 응답의 경우 예외가 발생합니다.

org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]

나머지 템플릿 교환 방법을 try에서 래핑해야합니까? 그러면 코드의 목적은 무엇입니까?



답변

구현하는 클래스를 ResponseErrorHandler만든 다음 인스턴스를 사용하여 나머지 템플릿의 오류 처리를 설정하려고합니다.

public class MyErrorHandler implements ResponseErrorHandler {
  @Override
  public void handleError(ClientHttpResponse response) throws IOException {
    // your error handling here
  }

  @Override
  public boolean hasError(ClientHttpResponse response) throws IOException {
     ...
  }
}

[...]

public static void main(String args[]) {
  RestTemplate restTemplate = new RestTemplate();
  restTemplate.setErrorHandler(new MyErrorHandler());
}

또한 Spring은 클래스 DefaultResponseErrorHandler를 가지고 있는데, 인터페이스를 구현하는 대신 확장 할 수 있습니다 handleError.

public class MyErrorHandler extends DefaultResponseErrorHandler {
  @Override
  public void handleError(ClientHttpResponse response) throws IOException {
    // your error handling here
  }
}

Spring이 HTTP 오류를 처리하는 방법에 대한 아이디어를 얻으 려면 소스 코드 를 살펴보십시오 .


답변

HttpStatusCodeException예외를 포착해야합니다 .

try {
    restTemplate.exchange(...);
} catch (HttpStatusCodeException exception) {
    int statusCode = exception.getStatusCode().value();
    ...
}


답변

Spring은 http 오류 코드를 예외로 영리하게 취급하고 예외 처리 코드에 오류를 처리 할 컨텍스트가 있다고 가정합니다. 예상대로 작동하도록 교환하려면 다음을 수행하십시오.

    try {
        return restTemplate.exchange(url, httpMethod, httpEntity, String.class);
    } catch(HttpStatusCodeException e) {
        return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
                .body(e.getResponseBodyAsString());
    }

그러면 응답에서 예상되는 모든 결과가 반환됩니다.


답변

또 다른 해결책은 “enlian”이이 게시물의 마지막 부분에서 설명한 것입니다.
http://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate

try{
     restTemplate.exchange(...)
} catch(HttpStatusCodeException e){
     String errorpayload = e.getResponseBodyAsString();
     //do whatever you want
} catch(RestClientException e){
     //no response payload, tell the user sth else 
}


답변

Spring은 매우 큰 http 상태 코드 목록에서 당신을 추상화합니다. 그것이 예외의 개념입니다. org.springframework.web.client.RestClientException 계층 구조를 살펴보십시오.

http 응답을 처리 할 때 가장 일반적인 상황을 매핑하는 많은 클래스가 있습니다. http 코드 목록은 정말 크므로 각 상황을 처리하는 코드를 작성하고 싶지 않을 것입니다. 그러나 예를 들어 HttpClientErrorException 하위 계층 구조를 살펴보십시오. 4xx 종류의 오류를 매핑하는 단일 예외가 있습니다. 깊이 들어가야한다면 할 수 있습니다. 그러나 HttpClientErrorException을 포착하기 만하면 서비스에 잘못된 데이터가 제공된 모든 상황을 처리 할 수 ​​있습니다.

DefaultResponseErrorHandler는 정말 간단하고 견고합니다. 응답 상태 코드가 2xx 계열이 아닌 경우 hasError 메서드에 대해 true를 반환합니다.


답변

에서 풀링 (http 클라이언트 팩토리) 또는로드 밸런싱 (유레카) 메커니즘을 사용 RestTemplate하는 new RestTemplate경우 클래스별로 생성 할 수 있는 사치가 없습니다 . 두 개 이상의 서비스를 호출하는 setErrorHandler경우 모든 요청에 ​​대해 전역 적으로 사용 되므로 사용할 수 없습니다 .

이 경우 잡는 HttpStatusCodeException것이 더 나은 옵션 인 것 같습니다.

유일한 다른 옵션은 여러 RestTemplate@Qualifier주석을 사용하여 인스턴스 입니다.

또한-그러나 이것은 내 취향입니다-나는 내 호출에 단단히 묶여있는 내 오류 처리를 좋아합니다.


답변

나는 이것을 아래와 같이 처리했습니다.

try {
  response = restTemplate.postForEntity(requestUrl, new HttpEntity<>(requestBody, headers), String.class);
} catch (HttpStatusCodeException ex) {
  response = new ResponseEntity<String>(ex.getResponseBodyAsString(), ex.getResponseHeaders(), ex.getStatusCode());
}