Spring Rest템플릿 예외 처리
코드 스니펫은 다음과 같습니다.기본적으로 에러 코드가 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]
나머지 템플릿 교환 방법은 꼭 포장해야 하나요?그러면 코드의 목적은 무엇일까요?
하다, , , 하다,ResponseErrorHandler
그런 다음 해당 인스턴스를 사용하여 rest 템플릿의 오류 처리를 설정합니다.
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());
}
에는 봄이라는 .DefaultResponseErrorHandler
, 「」를 덧쓰기하는 , 「」를 사용해 .」를 , 이것을 확장할 수 handleError
★★★★★★ 。
public class MyErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// your error handling here
}
}
Spring이 HTTP 오류를 처리하는 방법을 이해하려면 소스 코드를 확인하십시오.
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());
}
이렇게 하면 응답에서 예상된 결과가 모두 반환됩니다.
도 꼭 잡으세요.HttpStatusCodeException
★★★★
try {
restTemplate.exchange(...);
} catch (HttpStatusCodeException exception) {
int statusCode = exception.getStatusCode().value();
...
}
또 하나의 솔루션은, 이 투고 마지막에 「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을 잡는 것만으로 서비스에 불량 데이터가 제공된 모든 상황을 처리할 수 있습니다.
Default Response Error Handler는 매우 단순하고 견고합니다.응답 상태 코드가 2xx 패밀리가 아닌 경우 hasError 메서드에 대해 true를 반환합니다.
이하와 같이 대응했습니다.
try {
response = restTemplate.postForEntity(requestUrl, new HttpEntity<>(requestBody, headers), String.class);
} catch (HttpStatusCodeException ex) {
response = new ResponseEntity<String>(ex.getResponseBodyAsString(), ex.getResponseHeaders(), ex.getStatusCode());
}
매우 심플한 솔루션은 다음과 같습니다.
try {
requestEntity = RequestEntity
.get(new URI("user String"));
return restTemplate.exchange(requestEntity, String.class);
} catch (RestClientResponseException e) {
return ResponseEntity.status(e.getRawStatusCode()).body(e.getResponseBodyAsString());
}
풀링을 '(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);
마지막으로 교환 방식을 호출해야 합니다.
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
프리티 인쇄를 위해 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);
}
}
감사합니다:)
@carcaret의 답변을 조금 연장하려면...
응답 오류가 json 메시지에 의해 반환된다고 가정합니다.를 들어 는 API를 반환할 수 .204
상태 코드 오류 및 json 메시지를 오류 목록으로 표시합니다.이 경우 스프링이 오류로 간주하는 메시지와 그 사용 방법을 정의해야 합니다.
에러가 발생했을 경우 API는 다음과 같은 것을 샘플로 반환할 수 있습니다.
{ "errorCode":"TSC100" , "errorMessage":"The foo bar error happend" , "requestTime" : "202112827733" .... }
json 이상을 소비하고 사용자 지정 예외를 발생시키려면 다음과 같이 하십시오.
먼저 에러 오브젝트를 매핑하기 위한 클래스를 정의합니다.
//just to map the json to object
public class ServiceErrorResponse implements Serializable {
//setter and getters
private Object errorMessage;
private String errorCode;
private String requestTime;
}
에러 핸들러를 정의합니다.
public class ServiceResponseErrorHandler implements ResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return (response.getStatusCode().is4xxClientError() ||
response.getStatusCode().is5xxServerError());
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<ServiceErrorResponse> errorMessageExtractor =
new HttpMessageConverterExtractor(ServiceErrorResponse.class, messageConverters);
ServiceErrorResponse errorObject = errorMessageExtractor.extractData(response);
throw new ResponseEntityErrorException(
ResponseEntity.status(response.getRawStatusCode())
.headers(response.getHeaders())
.body(errorObject)
);
}
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
커스텀 예외는 다음과 같습니다.
public class ResponseEntityErrorException extends RuntimeException {
private ResponseEntity<ServiceErrorResponse> serviceErrorResponseResponse;
public ResponseEntityErrorException(ResponseEntity<ServiceErrorResponse> serviceErrorResponseResponse) {
this.serviceErrorResponseResponse = serviceErrorResponseResponse;
}
public ResponseEntity<ServiceErrorResponse> getServiceErrorResponseResponse() {
return serviceErrorResponseResponse;
}
}
사용방법:
RestTemplateResponseErrorHandler errorHandler = new
RestTemplateResponseErrorHandler();
//pass the messageConverters to errror handler and let it convert json to object
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
Rest 템플릿에서 예외를 처리하는 방법은 다음과 같습니다.
try {
return restTemplate.exchange("URL", HttpMethod.POST, entity, String.class);
}
catch (HttpStatusCodeException e)
{
return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
.body(e.getResponseBodyAsString());
}
이것은 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;
}
DefaultResponseErrorHandler 클래스의 hasError 메서드를 덮어쓰고 수정했습니다.
public class BadRequestSafeRestTemplateErrorHandler extends DefaultResponseErrorHandler
{
@Override
protected boolean hasError(HttpStatus statusCode)
{
if(statusCode == HttpStatus.BAD_REQUEST)
{
return false;
}
return statusCode.isError();
}
}
또한 이 핸들러를 restemplate bean용으로 설정해야 합니다.
@Bean
protected RestTemplate restTemplate(RestTemplateBuilder builder)
{
return builder.errorHandler(new BadRequestSafeRestTemplateErrorHandler()).build();
}
글로벌 예외 핸들러에서의 글로벌 예외 처리에 대해 읽고 다음 메서드를 추가합니다.이거면 될 거야
@ExceptionHandler( {HttpClientErrorException.class, HttpStatusCodeException.class, HttpServerErrorException.class})
@ResponseBody
public ResponseEntity<Object> httpClientErrorException(HttpStatusCodeException e) throws IOException {
BodyBuilder bodyBuilder = ResponseEntity.status(e.getRawStatusCode()).header("X-Backend-Status", String.valueOf(e.getRawStatusCode()));
if (e.getResponseHeaders().getContentType() != null) {
bodyBuilder.contentType(e.getResponseHeaders().getContentType());
}
return bodyBuilder.body(e.getResponseBodyAsString());
}
TestRestTemplate를 사용하는 옵션도 있습니다.모든 상태 코드를 수동으로 검증해야 하는 경우(네거티브테스트 케이스 등) 통합 및 E2E 테스트에 매우 유용합니다.
TestRestTemplate는 폴트 톨러런스입니다.즉, 4xx 및 5xx는 예외가 느려지지 않고 응답 엔티티와 그 상태 코드를 통해 검출할 수 있습니다.
사용해보십시오.@ControllerAdvice
이렇게 하면 예외를 한 번만 처리하고 모든 '커스텀'이 한 곳에서 예외를 처리할 수 있습니다.
예
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler{
@ExceptionHandler(MyException.class)
protected ResponseEntity<Object> handleMyException(){
MyException exception,
WebRequest webRequest) {
return handleExceptionInternal(
exception,
exception.getMessage(),
exception.getResponseHeaders(),
exception.getStatusCode(),
webRequest);
}
언급URL : https://stackoverflow.com/questions/38093388/spring-resttemplate-exception-handling
'sourcecode' 카테고리의 다른 글
리액트 라우터돔을 사용할 때 '기능 구성 요소를 참조할 수 없음'을 방지하려면 어떻게 해야 합니까? (0) | 2023.02.28 |
---|---|
요소가 존재하지 않는지 프로젝터 확인 (0) | 2023.02.23 |
사용자 정의 필터 기능이 있는 AngularJS 다중 필터 (0) | 2023.02.23 |
ORA-04082: 테이블 레벨 트리거에서 새 참조 또는 오래된 참조가 허용되지 않음 (0) | 2023.02.23 |
Wordpress 플러그인 슬라이더 회전 오류 (0) | 2023.02.23 |