以下はコードスニペットです。基本的に、私はエラーコードが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ステータスコードを取得します。その行でも例外がスローされますが、それは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
RestTemplate
でプール(http client factory)またはロードバランシング(eureka)メカニズムを使用する場合、クラスごとにnew RestTemplate
を作成する贅沢はありません。もしあなたが複数のサービスを呼んでいるのであればsetErrorHandler
を使うことはできません。
この場合、HttpStatusCodeException
をキャッチするのがより良い選択肢のようです。
唯一の他の選択肢は、@Qualifier
アノテーションを使って複数のRestTemplate
インスタンスを定義することです。
また - これは私自身の好みです - 私はエラー処理が私の呼び出しにぴったりと寄り添っているのが好きです。
Springは非常に非常に大きなhttpステータスコードのリストからあなたを抽象化します。それが例外の考え方です。 org.springframework.web.client.RestClientException階層を調べてください。
Httpレスポンスを扱うときに最も一般的な状況をマッピングするためのたくさんのクラスがあります。 httpコードリストは非常に大きく、各状況を処理するコードを作成したくないでしょう。しかし、例えば、HttpClientErrorExceptionサブ階層を調べてください。 4xx種類のエラーをマッピングするための例外が1つあります。あなたが深く行く必要があるなら、あなたはそれができます。しかし、HttpClientErrorExceptionをキャッチするだけで、不正なデータがサービスに提供されたあらゆる状況に対処できます。
DefaultResponseErrorHandlerは本当にシンプルでしっかりしています。応答ステータスコードが2xxファミリからではない場合、hasErrorメソッドに対して単にtrueを返します。
交換コードは以下の通りです:
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);
}
}
ありがとう:)