обработка исключений клиента Spring Feign

У меня есть какой-то клиент fiegn, чтобы отправить запрос другому микросервису.

@FeignClient(name="userservice")
public interface UserClient {

    @RequestMapping(
            method= RequestMethod.GET,
                      path = "/userlist")
    String getUserByid(@RequestParam(value ="id") String id);

}

Сейчас я отправляю такой запрос

try {
    String responseData = userClient.getUserByid(id);
    return responseData;
    }

catch(FeignException e)
 {
 logger.error("Failed to get user", id);
}

catch (Exception e) 
{
 logger.error("Failed to get user", id);
}

Здесь проблема в том, что если происходит какое-либо исключение FeignException, я не получаю никакого кода ошибки.

Мне нужно отправить соответствующие коды ошибок в другом APIS для отправки вызывающему абоненту

Итак, как извлечь код ошибки? Я хочу извлечь код ошибки и создать responseEntity

Я получил этот код, но не знаю, как именно я могу использовать его в своей функции.


person kcoder    schedule 06.03.2019    source источник


Ответы (4)


вы пытались реализовать FallbackFactory на своем воображаемом клиенте?

https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#spring-cloud-feign-hystrix-fallback

В методе create перед возвратом вы можете получить код статуса http с помощью этого фрагмента:

String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";

Пример:

@FeignClient(name="userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {

    @RequestMapping(
            method= RequestMethod.GET,
                      path = "/userlist")
    String getUserByid(@RequestParam(value ="id") String id);

}


@Component
static class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable cause) {

     String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";

     return new UserClient() {
        @Override
        public String getUserByid() {
            logger.error(httpStatus);
            // what you want to answer back (logger, exception catch by a ControllerAdvice, etc)
        }
    };
}

}

person rphlmr    schedule 06.03.2019
comment
исключение, ведьма была выбрана в резервной фабрике, не будет обнаружена советом контроллера - person KnockKnock; 26.11.2019
comment
В общем случае в контроллере будет несколько методов, поэтому мы продолжим, реализуя каждый метод, даже если все, что я хочу сделать, обрабатывать его для нескольких методов, а не для всех - person Akki; 16.04.2020

Не та же проблема, но в моей ситуации это помогло. FeignException OpenFeign не привязывается к определенному статусу HTTP (т.е.не использует аннотацию @ResponseStatus Spring), что делает Spring по умолчанию равным 500 всякий раз, когда сталкивается с FeignException. Это нормально, потому что FeignException может иметь множество причин, которые не могут быть связаны с конкретным статусом HTTP.

Однако вы можете изменить способ обработки исключений FeignExceptions в Spring. Просто определите ExceptionHandler, который обрабатывает FeignException

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(FeignException.class)
    public String handleFeignStatusException(FeignException e, HttpServletResponse response) {
        response.setStatus(e.status());
        return "feignError";
    }

}

В этом примере Spring возвращает тот же HTTP-статус, который вы получили.

person Srinath    schedule 21.05.2019
comment
как вы это настраиваете? это не работает для меня. Мне нужно добавить дополнительный код в конфигурацию, чтобы узнать об этом?? - person Stevers; 21.02.2020
comment
Как я могу вернуть тело ответа FeignException для статуса http, отличного от 2xx? - person Juan Rojas; 03.07.2020
comment
Это единственный ответ, который у меня сработал, спасибо! - person ConnorVanElswyk; 27.10.2020
comment
Несмотря на то, что это работает, это способствует плохой практике, заключающейся в утечке деталей реализации низкого уровня в стек. FeignClient используется на уровне приложения для предоставления некоторой ценности домену, он не имеет ничего общего с транспортным уровнем (то есть контроллерами, статутами http и т. Д.). Если вы хотите пойти по этому пути, я бы рекомендовал сначала обернуть FeignException в правильный домен, например UserNotFoundException и только потом с помощью метода, который вы предложили на последнем. - person th3n3rd; 14.05.2021

Я опаздываю на вечеринку, но вот мои 2 цента. У нас был такой же вариант использования для обработки исключений на основе кода ошибки, и мы использовали custom ErrorDecoder.

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        String requestUrl = response.request().url();
        Response.Body responseBody = response.body();
        HttpStatus responseStatus = HttpStatus.valueOf(response.status());

        if (responseStatus.is5xxServerError()) {
            return new RestApiServerException(requestUrl, responseBody);
        } else if (responseStatus.is4xxClientError()) {
            return new RestApiClientException(requestUrl, responseBody);
        } else {
            return new Exception("Generic exception");
        }
    }
}

Вернуть @Bean указанного выше класса в FeignClientConfiguration класс.

public class MyFeignClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

Используйте его как класс конфигурации для FeignClient.

@FeignClient(value = "myFeignClient", configuration = MyFeignClientConfiguration.class)

Затем вы можете обрабатывать эти исключения с помощью GlobalExceptionHandler.

person VaibS    schedule 22.05.2021
comment
вы можете удалить @Configuration на MyFeignClientConfiguration, поскольку класс создается через configuration = MyFeignClientConfiguration.class. - person Stanislas Klukowski; 27.05.2021

Для этого есть интерфейс ErrorDecored, как сказано в документации.

Вышеупомянутый ответ о FallbackFactory жизнеспособен, но относится к другому уровню абстракции.

person kpankov    schedule 26.08.2020
comment
Этот URL-адрес просто ведет к общей документации клиента Feign, не включая обработку исключений. - person ConnorVanElswyk; 27.10.2020