Настройка Исключения Zuul

у меня есть сценарий в Zuul, где Служба, что URL-адрес маршрутизируется тоже может быть вниз . Таким образом, тело reponse выбрасывается С 500 статусом HTTP и ZuulException в ответе тела JSON.

{
  "timestamp": 1459973637928,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "com.netflix.zuul.exception.ZuulException",
  "message": "Forwarding error"
}

все, что я хочу сделать, это настроить или удалить ответ JSON и, возможно, изменить код состояния HTTP.

Я попытался создать обработчик исключений с @ControllerAdvice, но исключение не захватывается обработчик.

обновления:

Так я продлил фильтр Зуул я вижу попадание в способ запуска после ошибки был казнен как изменить ответ тогда. Вот что я получил до сих пор. Я где-то читал о SendErrorFilter, но как это реализовать и что он делает?

public class CustomFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {

        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        final RequestContext ctx = RequestContext.getCurrentContext();
        final HttpServletResponse response = ctx.getResponse();
        if (HttpStatus.INTERNAL_SERVER_ERROR.value() == ctx.getResponse().getStatus()) {
            try {
                response.sendError(404, "Error Error"); //trying to change the response will need to throw a JSON body.
            } catch (final IOException e) {
                e.printStackTrace();
            } ;
        }

        return null;
    }

добавил Это в класс, который имеет @EnableZuulProxy

@Bean
public CustomFilter customFilter() {
    return new CustomFilter();
}

4 ответов


мы, наконец, получили эту работу [закодированную одним из моих коллег]: -

public class CustomErrorFilter extends ZuulFilter {

    private static final Logger LOG = LoggerFactory.getLogger(CustomErrorFilter.class);
    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return -1; // Needs to run before SendErrorFilter which has filterOrder == 0
    }

    @Override
    public boolean shouldFilter() {
        // only forward to errorPath if it hasn't been forwarded to already
        return RequestContext.getCurrentContext().containsKey("error.status_code");
    }

    @Override
    public Object run() {
        try {
            RequestContext ctx = RequestContext.getCurrentContext();
            Object e = ctx.get("error.exception");

            if (e != null && e instanceof ZuulException) {
                ZuulException zuulException = (ZuulException)e;
                LOG.error("Zuul failure detected: " + zuulException.getMessage(), zuulException);

                // Remove error code to prevent further error handling in follow up filters
                ctx.remove("error.status_code");

                // Populate context with new response values
                ctx.setResponseBody(“Overriding Zuul Exception Body”);
                ctx.getResponse().setContentType("application/json");
                ctx.setResponseStatusCode(500); //Can set any error code as excepted
            }
        }
        catch (Exception ex) {
            LOG.error("Exception filtering in custom error filter", ex);
            ReflectionUtils.rethrowRuntimeException(ex);
        }
        return null;
    }
}

у меня была такая же проблема и я смог решить ее более простым способом

просто поместите это в фильтр run() метод

    if (<your condition>) {
        ZuulException zuulException = new ZuulException("User message", statusCode, "Error Details message");
        throw new ZuulRuntimeException(zuulException);
    }

и SendErrorFilter доставит пользователю сообщение с желаемым statusCode.

это исключение в шаблоне исключения выглядит не совсем хорошо, но оно работает здесь.


пересылка часто выполняется фильтром, в этом случае запрос даже не доходит до контроллера. Это объясняет, почему ваш @ControllerAdvice не работает.

Если вы пересылаете контроллер, чем должен работать @ControllerAdvice. Проверьте, создает ли spring экземпляр класса с аннотацией @ControllerAdvice. Для этого поместите точку останова в классе и посмотрите, будет ли она поражена.

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

эти шаги должны помочь вам решить вопрос.

в вашем классе, аннотированном @ControllerAdvice, добавьте метод ExceptionHandler, аннотированный @ExceptionHandler(Exceptionhandler.class), который должен поймать каждое исключение.

EDIT: Можно попытаться добавить собственный фильтр, который преобразует ответ на ошибку, возвращаемый Zuulfilter. Там вы можете изменить отвечайте, как хотите.

как можно настроить ответ на ошибку, объясняется здесь:

обработка исключений для фильтра весной

правильное размещение фильтра может быть немного сложнее. Не совсем уверен в правильной позиции, но вы должны знать порядок ваших фильтров и место, где вы обрабатываете исключение.

Если вы поместите его перед Zuulfilter, вы должны закодировать обработку ошибок после вызова doFilter().

Если вы разместите его после Zuulfilter, вы должны закодировать обработку ошибок перед вызовом doFilter ().

добавление точек останова в фильтр до и после doFilter() может помочь найти правильное положение.


вот шаги, чтобы сделать это с @ControllerAdvice:

  1. добавить фильтр типа error и пусть он будет запущен до SendErrorFilter в самом зуул.
  2. обязательно удалите ключ, связанный с исключением из RequestContext предупреждения SendErrorFilter выполнить.
  3. использовать RequestDispatcher переслать запрос на ErrorController -- объяснил ниже.
  4. добавьте класс @RestController и сделайте его extends AbstractErrorController, и повторно бросить исключение снова (добавьте его на шаге выполнения нового фильтра ошибок с помощью (ключ, исключение), получите его из RequestContext в свой контроллер).

исключение теперь будет поймано в вашем классе @ControllerAdvice.