স্প্রিং রিস্টেম্প্লেট ব্যতিক্রম হ্যান্ডলিং


124

নীচে কোড স্নিপেট রয়েছে; মূলত, ত্রুটি কোডটি 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]

আমার কি সত্যিই চেষ্টা করার বাকী টেম্পলেট এক্সচেঞ্জ পদ্ধতি মোড়ানো দরকার? তাহলে কোডের উদ্দেশ্য কী হবে?


দয়া করে আবেদনের কোডটি শেয়ার করুন ()
মুদাসসর

উত্তর:


128

আপনি প্রয়োগ করে এমন একটি শ্রেণি তৈরি করতে চান 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());
}

এছাড়াও, বসন্তের ক্লাস রয়েছে DefaultResponseErrorHandler, যা আপনি কেবলমাত্র handleErrorপদ্ধতিটিকে ওভাররাইড করতে চান যদি আপনি ইন্টারফেস প্রয়োগের পরিবর্তে প্রসারিত করতে পারেন ।

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

বসন্ত কীভাবে HTTP ত্রুটি পরিচালনা করে তার ধারণা পেতে এর উত্স কোডটি একবার দেখুন ।


1
আমার কাছে রেস্টটেম্প্লেটের 1 টি উদাহরণ রয়েছে যা আমি বিভিন্ন কলগুলির জন্য পুনরায় ব্যবহার করি। আমাকে বিভিন্ন কল থেকে ত্রুটিগুলি আলাদাভাবে পরিচালনা করতে হবে - দৃশ্যত গ্লোবাল হ্যান্ডলারের সাথে এটি করার কোনও উপায় নেই - আমাকে অনুরোধ অনুযায়ী একটি হ্যান্ডলার সরবরাহ করতে হবে।
এমভিএমএন

4
এই ত্রুটি হ্যান্ডলারের সাহায্যে আমি সর্বদা একটি পাই ResourceAccessExceptionকারণ এস RestTemplate.doExecuteক্যাচ করে IOExceptionএবং একটি ছুঁড়ে ResourceAccessException। আমি কি ভুল করছি?
ফেডেরিকো বেলুচি

আমি এটি ডিফল্ট রেসপনসইররহ্যান্ডলার বাড়িয়ে সমাধান করতে সক্ষম হয়েছি।
ক্রেঙ্গুটা এস

48

আপনার একটি HttpStatusCodeExceptionব্যতিক্রম ধরা উচিত :

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

37
আইএমও এর প্রতিক্রিয়া সর্বদা যথাযথ স্থিতি কোড নিয়ে আসা উচিত, অন্যথায় কোডগুলির উদ্দেশ্য the
বৈভব

5
আমি @ বৈভব আপত্তিটি বোঝার বিষয়ে নিশ্চিত নই: এইচটিটিপিস্ট্যাটাসকোডএক্সসেপশন ধরা কোনও ভুল কোডের জন্য নয়, তবে কারণ বেশিরভাগ ক্ষেত্রেই ব্যতিক্রম সর্বদা নিক্ষেপ করা হয় এবং তাই আপনার যদি (কোড == মান) কখনও কার্যকর করা যায় না।
স্টেফানো স্কর্পান্তি

1
ব্যতিক্রম জাভাতে খুব ব্যয়বহুল। এটি মাঝে মধ্যে, অপ্রত্যাশিত কারণে (যার জন্য নাম) ঠিক আছে তবে এর পরিবর্তে আপনার পরিবর্তে অন্যান্য সমাধান সন্ধান করা উচিত।
আগস্টন হরভাথ

11
"খুব দামী"? এর চেয়ে বেশি ব্যয়বহুল, বলুন, এইচটিটিপি কল করছেন?
আইসডড্যান্ট

4
@ রাফেলবেচারারামে - এইচটিপিস্ট্যাটাসকোডএক্সেপশন .get রেসপোনসবডিএস্ট্রিং () বা এইচটিপিস্ট্যাটাসকোডএক্সেপশন.সেটস্পোনসবডিএএসবাইটআরে ()।
ডেভ

45

স্প্রিং চতুরতার সাথে HTTP ত্রুটি কোডগুলি ব্যতিক্রম হিসাবে বিবেচনা করে এবং ধরে নেয় যে আপনার ব্যতিক্রম হ্যান্ডলিং কোডটিতে ত্রুটিটি পরিচালনা করার প্রসঙ্গ রয়েছে। আপনি যেমনটি আশা করেন তেমন ফাংশন বিনিময় পেতে, এটি করুন:

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

এটি প্রতিক্রিয়া থেকে সমস্ত প্রত্যাশিত ফলাফল প্রত্যাবর্তন করবে।


2
ত্রুটিগুলির জন্য প্রতিক্রিয়া বডি পেতে আপনার ডিফল্ট এসডিকে-র চেয়ে আলাদা এইচটিপিপিলেট ব্যবহার করতে হবে
রেজার

26

আরেকটি সমাধান হ'ল "এনলিয়ান" এর পোস্টের শেষে এখানে বর্ণিত একটি: http ://springinpੈਕਟ.com.com/2013/10/07/andling-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 
}

4
ত্রুটিগুলির জন্য প্রতিক্রিয়া বডি পেতে আপনার ডিফল্ট এসডিকে-র চেয়ে আলাদা এইচটিপিপি্লিয়েন্ট ব্যবহার করতে হবে (উদাহরণস্বরূপ এপাচি কমন্স এইচটিটিপিসিলেট)
রেজার

17

স্প্রিং আপনাকে http অবস্থানের কোডের খুব খুব বড় তালিকা থেকে বিমূর্ত করে। ব্যতিক্রম সম্পর্কে ধারণা এটি That Org.springframework.web.client.RestClientException হাইয়ারার্কিতে একবার দেখুন

HTTP প্রতিক্রিয়াগুলির সাথে ডিল করার সময় সর্বাধিক সাধারণ পরিস্থিতিগুলির মানচিত্র করার জন্য আপনার কাছে ক্লাসের একগুচ্ছ রয়েছে। HTTP কোডের তালিকাটি সত্যিই বড়, আপনি প্রতিটি পরিস্থিতি পরিচালনার জন্য লিখিত কোড চাইবেন না। তবে উদাহরণস্বরূপ, HTTPClientErrorException সাব-হায়ারার্কি একবার দেখুন। 4XX প্রকারের ত্রুটি ম্যাপ করার জন্য আপনার একক ব্যতিক্রম রয়েছে। আপনার যদি গভীর দিকে যেতে হয় তবে আপনি পারেন। তবে কেবল HTTPClientErrorException ধরা দিয়ে আপনি যে কোনও পরিস্থিতি যেখানে পরিষেবাতে খারাপ ডেটা সরবরাহ করা হয়েছিল তা পরিচালনা করতে পারেন।

DefaultResponseErrorHandler আসলেই সহজ এবং শক্ত। যদি প্রতিক্রিয়া স্থিতি কোডটি 2xx এর পরিবার থেকে না হয় তবে এটি হ'রআরার পদ্ধতির জন্য ঠিক ফিরে আসে।


বাবু, ব্যাখ্যার জন্য ধন্যবাদ। আপনি কীভাবে এই গাছটি ব্যতিক্রম শ্রেণিবিন্যাসের সাথে তৈরি করেছিলেন?
একা দাঁড়িয়ে

1
আরে মানুষ, আমি Eclipse ব্যবহার করেছি। টাইপ অনুসন্ধানকারীটি খোলার জন্য কেবল নিয়ন্ত্রণ + শিফট + টি টিপুন এবং রেস্টক্লিয়েন্টএক্সসেপশন টাইপ করুন। ফলাফলগুলি থেকে রেস্টক্লিয়েন্টএক্সেপশনে ডাবল ক্লিক করুন, গ্রহন আপনার জন্য সেই শ্রেণিটি খুলবে। তারপরে, শ্রেণীর নামের উপরে মাউস কার্সারটি রাখুন (যেখানে এটি "পাবলিক ক্লাস রেস্টক্লিয়েন্টএক্সেপশন ..." বলে থাকে এবং কন্ট্রোল + টি টিপুন You আপনি যে স্তরক্রমটি দেখতে পাবেন
পেরিমোশ

তুমি কি চেষ্টা করেছ?
পেরিমোষ

1
Intellij মধ্যে BTW এটি হল: -> ডায়াগ্রাম বিল্ড প্রকল্পের গাছ এবং জন্য Ctrl + Alt + + ইউ, বা ডান মাউস ক্লিকে বর্গ ক্লিক করুন
একা দাঁড়ানো

3

আপনি যদি নিজের সাথে পুলিং (HTTP ক্লায়েন্ট কারখানা) বা লোড ব্যালেন্সিং (ইউরেকা) প্রক্রিয়া ব্যবহার করেন তবে আপনার প্রতি ক্লাস RestTemplateতৈরির বিলাসিতা হবে না new RestTemplate। যদি আপনি একাধিক পরিষেবা কল করছেন তবে আপনি ব্যবহার করতে পারবেন না setErrorHandlerকারণ যদি আপনার সমস্ত অনুরোধের জন্য বিশ্বব্যাপী এটি ব্যবহৃত হয়।

এই ক্ষেত্রে, ধরাটি HttpStatusCodeExceptionআরও ভাল বিকল্প বলে মনে হচ্ছে।

আপনার কাছে কেবলমাত্র অন্য বিকল্পটি টীকাগুলি RestTemplateব্যবহার করে একাধিক উদাহরণ সংজ্ঞায়িত করা @Qualifier

এছাড়াও - তবে এটি আমার নিজস্ব স্বাদ I আমার কলগুলিতে আমার ত্রুটিটি কঠোরভাবে হ্যান্ডলিং করা পছন্দ করি।


3

আমি এটি নীচের মত পরিচালনা করেছি:

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

1

এক্সচেঞ্জের কোডটি নীচে রয়েছে :

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);

প্রেটি প্রিন্টিংয়ের জন্য আমি জিসন লাইব্রেরি ব্যবহার করেছি। এখানে গ্রেড: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);
    }
}

ধন্যবাদ :)


2
'org.springframework.web.client.HttpClientErrorException' 'org.springframework.web.client.HttpStatusCodeException' এর একটি সাবক্লাস। আপনি যদি ইতিমধ্যে HttpStatusCodeException ধরছেন এবং উপরের দুটি ব্যতিক্রম হ্যান্ডেল করার ক্ষেত্রে আলাদা কিছু না করে থাকেন তবে আপনাকে HTTPClientErrorException ধরার দরকার নেই।
দ্য প্রোটন-রিসার্জেন্স

0

খুব সহজ সমাধান হতে পারে:

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());
}

-1

এখানে এইচটিটিপিএস সহ আমার পোস্ট পদ্ধতি যা কোনও ধরণের খারাপ প্রতিক্রিয়ার জন্য একটি প্রতিক্রিয়া দেবে।

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;
}

3
ত্রুটিগুলির জন্য প্রতিক্রিয়া বডি পেতে আপনার ডিফল্ট এসডিকে-র চেয়ে আলাদা এইচটিপিপি্লিয়েন্ট ব্যবহার করতে হবে (উদাহরণস্বরূপ এপাচি কমন্স এইচটিটিপিসিলেট)
রেজার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.