自定义Zuulexception

我在Zuul有一个场景,其中URL路由的服务也可能已关闭。 因此,响应主体在JSON主体响应中被抛出500 HTTP Status和ZuulException。

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

我想要做的就是自定义或删除JSON响应,并可能更改HTTP状态代码。

我试图用@ControllerAdvice创建一个exception处理程序,但处理程序没有抓住exception。

更新:

所以我扩展了Zuulfilter,我可以看到它在执行错误后进入run方法,然后如何更改响应。 以下是我到目前为止所得到的。 我在某处读到了有关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(); } 

我们终于得到了这个工作[由我的一位同事编写]: –

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

我有同样的问题,能够以更简单的方式解决它

把它放到你的filterrun()方法中

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

SendErrorFilter将向用户传递具有所需statusCode的消息。

exception模式中的此exception看起来不太好,但它在这里工作。

转发通常由filter完成,在这种情况下,请求甚至不会到达控制器。 这可以解释为什么你的@ControllerAdvice不起作用。

如果你在控制器中转发比@ControllerAdvice应该工作。 检查spring是否创建了使用@ControllerAdvice注释的类的实例。 对于那个地方,在class级中有一个断点,看它是否被击中。

在转发应该发生的控制器方法中也添加一个断点。 可能是你意外调用另一个控制器方法而不是你检查?

这些步骤可以帮助您解决问题。

在使用@ControllerAdvice注释的类中,添加一个使用@ExceptionHandler(Exception.class)注释的ExceptionHandler方法,该方法应捕获每个Exception。

编辑:您可以尝试添加自己的filter,转换Zuulfilter返回的错误响应。 在那里,您可以根据需要更改响应。

如何定制错误响应的解释如下:

弹簧filter的exception处理

正确放置filter可能有点棘手。 不完全确定正确的位置,但您应该了解filter的顺序以及处理exception的位置。

如果将它放在Zuulfilter之前,则必须在调用doFilter()之后编写error handling代码。

如果将它放在Zuulfilter之后,则必须在调用doFilter()之前编写error handling代码。

在doFilter()之前和之后在filter中添加断点可能有助于找到正确的位置。

以下是使用@ControllerAdvice执行此操作的步骤:

  1. 首先添加一个类型为error的filter, SendErrorFilter在zuul本身的SendErrorFilter之前运行。
  2. 确保从SendErrorFilter删除与exception关联的键,以防止执行SendErrorFilter
  3. 使用RequestDispatcher将请求转发给ErrorController – 如下所述。
  4. 添加一个@RestController类并使其扩展AbstractErrorController ,并再次重新抛出exception(在使用(key,exception)执行新的错误filter的步骤中添加它,从控制器的RequestContext中获取它)。

现在将在您的@ControllerAdvice类中捕获exception。