Как реализовать декодер ошибок для нескольких поддельных клиентов

У меня есть несколько поддельных клиентов в приложении Spring Boot. Я использую совет контроллера для обработки пользовательских исключений для каждого воображаемого клиента.

Вот мой совет контроллера, который обрабатывает два настраиваемых исключения (по одному для каждого клиента: client1 и client2):

   @ControllerAdvice
    public class ExceptionTranslator implements ProblemHandling {
         @ExceptionHandler
        public ResponseEntity<Problem> handleCustomClient1Exception(CustomException1 ex, NativeWebRequest request) {
            Problem problem = Problem.builder()
                    .title(ex.getTitle())
                    .detail(ex.getMessage())
                    .status(ex.getStatusType())
                    .code(ex.getCode())
                    .build();
            return create(ex, problem, request);
        }
         @ExceptionHandler
        public ResponseEntity<Problem> handleCustomClient2Exception(CustomException2 ex, NativeWebRequest request) {
                Problem problem = Problem.builder()
                        .title(ex.getTitle())
                        .detail(ex.getMessage())
                        .status(ex.getStatusType())
                        .code(ex.getCode())
                        .build();
                return create(ex, problem, request);
            }
        }

Я реализовал декодер ошибок для симуляции client1.

public class ClientErrorDecoder implements ErrorDecoder {
    final ObjectMapper mapper;


    public ClientErrorDecoder() {
        this.mapper = new ObjectMapper();
    }

@Override
public Exception decode(String methodKey, Response response) {
    ExceptionDTO exceptionDTO;

    try {
        exceptionDTO = mapper.readValue(response.body().asInputStream(), ExceptionDTO.class);
    } catch (IOException e) {
        throw new RuntimeException("Failed to process response body.", e);
    }


    return new CustomException1(exceptionDTO.getDetail(), exceptionDTO.getCode(), exceptionDTO.getTitle(), exceptionDTO.getStatus());


}

}

Я также настроил симуляцию для использования этого декодера ошибок для этого конкретного клиента следующим образом:

feign:
client:
    config:
        client1:
            errorDecoder: feign.codec.ErrorDecoder.Default

Мой вопрос: как лучше всего обрабатывать более одного ложного клиентского исключения? Должен ли я использовать тот же декодер ошибок и рассматривать их ответы как общее исключение? Или мне нужно создать декодер ошибок для каждого симулятора клиента?


person YanetP1988    schedule 29.05.2019    source источник


Ответы (1)


Быстрый ответ

Если вы работаете с разными API, ответы об ошибках не будут иметь одинаковый формат. Следовательно, обработка их по отдельности кажется лучшим подходом.

Примечания

Из вашего примера кажется, что вы определили пользовательский ErrorDecoder, который может не использоваться, потому что вы также настроили симуляцию на использование декодера ошибок по умолчанию для вашего client1 в файле свойств. Даже если вы где-то определили класс @Configuration с bean-компонентом для своего пользовательского ClientErrorDecoder, в документации Spring Cloud упоминается, что свойства конфигурации имеют приоритет над аннотацией @Configuration.

Если мы создадим и компонент @Configuration, и свойства конфигурации, свойства конфигурации выиграют. Он переопределит значения @Configuration. Но если вы хотите изменить приоритет на @Configuration, вы можете изменить feign.client.default-to-properties на false.

Пример

Вот гипотетическая сокращенная конфигурация для обработки нескольких поддельных клиентов с разными декодерами ошибок:

Client1: вы говорите fign, что нужно загрузить bean-компоненты, определенные в классе CustomFeignConfiguration для client1

@FeignClient(name = "client1", configuration = {CustomFeignConfiguration.class})
public interface Client1 {...}

Client2: Client2 будет использовать Feign ErrorDecoder по умолчанию, поскольку конфигурация не указана. (Выдает FeignException при ошибке)

@FeignClient(name = "client2")
public interface Client2 {...}

Конфигурация: будьте осторожны, если вы добавите @Configuration в CustomFeignConfiguration, то ClientErrorDecoder bean будет использоваться для каждого загруженного имитационного клиента (в зависимости от поведения сканирования компонентов вашего приложения)

public class CustomFeignConfiguration {
    @Bean
    public ClientErrorDecoder clientErrorDecoder(ObjectMapper objectMapper) {
        return new ClientErrorDecoder(objectMapper);
    }
}

Эту конфигурацию можно также выполнить с помощью файла свойств.

Дополнительное замечание

С моей точки зрения, вам даже не нужен совет контроллера. Если вы используете аннотацию Spring Web @ResponseStatus, вы можете указать, какой код состояния HTTP должен быть отправлен обратно с телом исключения, созданным вашим пользовательским ErrorDecoder.

Полезные ресурсы

person user3793803    schedule 14.11.2019