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
}
이 튜토리얼이나 다른 튜토리얼 중 어느 것도 나를 위해 일하지 않았습니다. RestTemplate은 단순히 쓰레기입니다. 다른 사람들이이 끔찍한 일에 시간을 낭비하지 않도록 고려하도록이 글을 쓰고 있습니다. restTemplate.exchange를 호출하고 400 상태 코드를 얻습니다. 예외도 해당 줄에서 throw되지만 HttpStatusCodeException이 아니라 ResourceAccessException입니다. 나는 Object와 String을 교환하려고 시도했습니다. 나는 완전히 쓸모없는 ResponseErrorHandler를 포함하려고 시도했습니다.
RestTemplate으로 원하는 것을 할 수없는 것도 처음이 아니며 오랫동안 사용하지도 않았습니다. 시간을 낭비하지 마십시오.
예를 들어 다음을 사용할 수 있습니다.
Apache HttpClient : https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
또는 OkHttp3 : https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
Spring은 매우 큰 http 상태 코드 목록에서 당신을 추상화합니다. 그것이 예외의 개념입니다. org.springframework.web.client.RestClientException 계층 구조를 살펴보십시오.
http 응답을 처리 할 때 가장 일반적인 상황을 매핑하는 많은 클래스가 있습니다. http 코드 목록은 매우 커서 각 상황을 처리하는 코드를 작성하고 싶지 않을 것입니다. 그러나 예를 들어 HttpClientErrorException 하위 계층 구조를 살펴보십시오. 4xx 종류의 오류를 매핑하는 단일 예외가 있습니다. 깊이 들어가야한다면 할 수 있습니다. 그러나 HttpClientErrorException을 포착하기 만하면 서비스에 잘못된 데이터가 제공된 모든 상황을 처리 할 수 있습니다.
DefaultResponseErrorHandler는 정말 간단하고 견고합니다. 응답 상태 코드가 2xx 계열이 아닌 경우 hasError 메서드에 대해 true를 반환합니다.
에서 풀링 (http 클라이언트 팩토리) 또는로드 밸런싱 (유레카) 메커니즘을 사용 RestTemplate
하는 new RestTemplate
경우 클래스별로 생성 할 수 있는 사치가 없습니다 . 두 개 이상의 서비스를 호출하는 setErrorHandler
경우 모든 요청에 대해 전역 적으로 사용 되므로 사용할 수 없습니다 .
이 경우 잡는 HttpStatusCodeException
것이 더 나은 옵션 인 것 같습니다.
유일한 다른 옵션 RestTemplate
은 @Qualifier
주석을 사용하여 여러 인스턴스 를 정의하는 것 입니다.
또한-그러나 이것은 내 취향입니다-나는 내 호출에 단단히 묶여있는 내 오류 처리를 좋아합니다.
교환 코드는 다음과 같습니다 .
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException
예외 RestClientException
가 HttpClientErrorException
있고 HttpStatusCodeException
예외입니다.
그렇게 RestTemplete
이 발생 시킬수 있습니다 HttpClientErrorException
및 HttpStatusCodeException
예외입니다. 예외 개체에서 다음과 같은 방법으로 정확한 오류 메시지를 얻을 수 있습니다.exception.getResponseBodyAsString()
다음은 예제 코드입니다 .
public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class<?> responseObject) {
printLog( "Url : " + url);
printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject));
try {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
long start = System.currentTimeMillis();
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue());
printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody()));
long elapsedTime = System.currentTimeMillis() - start;
printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)");
if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) {
return responseEntity.getBody();
}
} catch (HttpClientErrorException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}catch (HttpStatusCodeException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}
return null;
}
다음은 코드 설명입니다 .
이 방법에서는 요청 및 응답 클래스를 전달해야합니다. 이 메서드는 요청 된 개체로 응답을 자동으로 구문 분석합니다.
우선 메시지 변환기를 추가해야합니다.
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
그런 다음 requestHeader
. 다음은 코드입니다.
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
마지막으로 exchange 메소드를 호출해야합니다.
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
prety 인쇄를 위해 Gson 라이브러리를 사용했습니다. 여기 gradle이 있습니다.compile 'com.google.code.gson:gson:2.4'
다음 코드를 호출하여 응답을받을 수 있습니다.
ResponseObject response=new RestExample().callToRestService(HttpMethod.POST,"URL_HERE",new RequestObject(),ResponseObject.class);
다음은 전체 작업 코드입니다 .
import com.google.gson.GsonBuilder;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
public class RestExample {
public RestExample() {
}
public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class<?> responseObject) {
printLog( "Url : " + url);
printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject));
try {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
long start = System.currentTimeMillis();
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue());
printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody()));
long elapsedTime = System.currentTimeMillis() - start;
printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)");
if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) {
return responseEntity.getBody();
}
} catch (HttpClientErrorException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}catch (HttpStatusCodeException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}
return null;
}
private void printLog(String message){
System.out.println(message);
}
}
감사 :)
다음은 모든 유형의 잘못된 응답에 대한 응답 본문을 반환하는 HTTPS를 사용하는 내 POST 메서드입니다.
public String postHTTPSRequest(String url,String requestJson)
{
//SSL Context
CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
//Initiate REST Template
RestTemplate restTemplate = new RestTemplate(requestFactory);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//Send the Request and get the response.
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
ResponseEntity<String> response;
String stringResponse = "";
try {
response = restTemplate.postForEntity(url, entity, String.class);
stringResponse = response.getBody();
}
catch (HttpClientErrorException e)
{
stringResponse = e.getResponseBodyAsString();
}
return stringResponse;
}
참고URL : https://stackoverflow.com/questions/38093388/spring-resttemplate-exception-handling
'developer tip' 카테고리의 다른 글
슬라이스를 선언하거나 슬라이스를 만드시겠습니까? (0) | 2020.09.18 |
---|---|
asp.net mvc보기에서 문자열을 html로 표시 (0) | 2020.09.18 |
git 프록시를 기본 구성으로 재설정 (0) | 2020.09.17 |
(임의의) 필드 이름으로 구조체 배열을 정렬하는 가장 짧은 방법은 무엇입니까? (0) | 2020.09.17 |
Java에서 이진 형식으로 정수 상수를 정의 할 수 있습니까? (0) | 2020.09.17 |