如何在不向用户显示堆栈跟踪的情况下处理servlet过滤器中的错误状态? [英] How do I handle error states in servlet filters without showing the user a stack trace?

查看:116
本文介绍了如何在不向用户显示堆栈跟踪的情况下处理servlet过滤器中的错误状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究Jetty / RESTEasy应用。如果我从我的一个REST端点抛出 WebApplicationException(myResponse),它会将给定的响应发送给客户端。

I'm working on a Jetty/RESTEasy app. If I throw a WebApplicationException(myResponse) from one of my REST endpoints, it sends the given response to the client.

当过滤器检测到错误时,我想要相同的行为:

When a filter detects an error, I want the same behavior:


  1. 它应该从继续执行停止执行,并且

  2. 它应该给用户一个明确的,JSON格式的错误,不包括堆栈跟踪。

显然,只需写入响应流,返回即可在 doFilter 方法中工作。但是这对于 doFilter 调用的其他方法不起作用。

Obviously, just writing to the response stream and returning works from within the doFilter method. But this doesn't work for other methods called by doFilter.

抛出任何异常都符合条件#1但是我还没有想出一个理智的方式来满足条件#2。 (你可以在底部看到我最好的尝试。)

Throwing any exception will meet condition #1 but I haven't figured out a sane way to meet condition #2 then. (You can see my best attempt at the bottom.)

正如Perception在他的回答中解释的那样, WebApplicationException s是像过滤器的上下文中的任何其他异常一样处理,因此给用户一个漂亮的丑陋堆栈跟踪。

As Perception explained in his answer, WebApplicationExceptions are treated like any other exception in the context of a Filter, and therefore give the user a nice ugly stack trace.

所以,总结一下我的问题:

So, to sum up my questions:


  • serveltt容器是否有任何等价于抛出新的WebApplicationException(响应)

  • 也许更重要的是,其他java项目如何处理这个?

我有这个代码在一个过滤器中,它可以工作,但我更喜欢一个更优雅的解决方案,自动适用于所有过滤器:

I have this code in one filter and it works, but I'd prefer a more elegant solution that automatically applies to all filters:

public void doFilter(final ServletRequest   request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
    try {
        doFilterOrThrow(request, response, chain);
    } catch (WebApplicationException e) {
        Response res = e.getResponse();
        ((HttpServletResponse) response).sendError(res.getStatus(), (String) res.getEntity());
    }
}


推荐答案

您提到的Web应用程序异常的具体处理仅在JAX-RS容器的上下文中定义,顺便说一句, 与Servlet容器相同。

The specific handling you mention for web application exceptions is only defined within the context of a JAX-RS container, which, by the way, is not the same thing as a Servlet container.

Web过滤器由Servlet容器处理,该容器不知道或不关心同一应用程序服务器中是否存在JAX-RS容器。它也不知道或不关心Web应用程序异常。因此,当您从过滤器中抛出WAE时,它被视为与任何其他异常相同(带有堆栈跟踪的服务器错误,或者如果您在Web应用程序中设置了一个预配置的错误页面)。

Web filters are handled by the Servlet container, which does not know or care that a JAX-RS container exists within the same application server. It also does not know or care about web application exceptions. So when you throw the WAE from within the filter it is treated just the same as any other exception (server error with a stack trace, or a preconfigured error page if you set one up in your web application).

在我看来,如果您通过过滤器向客户端指示错误,可以直接写入响应流。但是,如果您正在尝试利用某些现有的JAX-RS逻辑,那么(RESTEasy特定的)解决方案是将请求标记为过滤器中的错误,然后使用提供程序类在JAX-RS中生成WAE。示例:

It would seem to me if you are indicating an error to the client you could simply do so from the filter, by writing directly to the response stream. But if you are trying to leverage some existing JAX-RS logic then a (RESTEasy specific) solution would be to flag the request as error'ed out in your filter, then generate a WAE in JAX-RS, using a provider class. Example:

@WebFilter(urlPatterns = "*")
public class ForwardingFilter implements Filter {

    @Override
    public void destroy() {
        return;
    }

    @Override
    public void doFilter(final ServletRequest request,
            final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        // Add an error response to be processed by the JAX-RS container.
        // This would obviously be based on some condition.
        request.setAttribute("errorResponse",
                Response.status(500).entity("Didn't work out!").build());
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        return;
    }
}

@Provider
@ServerInterceptor
@HeaderDecoratorPrecedence
@RequestScoped
public class ForwardingHandlerProvider implements PreProcessInterceptor {

    @Override
    public ServerResponse preProcess(final HttpRequest request,
            final ResourceMethod method) throws Failure,
            WebApplicationException {
        final Response errorResponse = (Response) request
                .getAttribute("errorResponse");
        if (errorResponse != null)
            throw new WebApplicationException(errorResponse);
        return null;
    }
}

由于提供商存在于JAX-RS土地上, Web应用程序异常根据JAX-RS规范第3.3.4节的规则进行处理,您可以在客户端获得所需的响应。

Since the provider exists in JAX-RS land, the web application exception is processed according to the rules of Section 3.3.4 of the JAX-RS specification, and you get the desired response at the client side.

*编辑:*

最重要的是,没有标准的Java EE规定方式(目前)以集中的方式处理servlet异常,类似于什么可在JAX-RS中使用。既然你正在使用JBoss / RestEASY,你可以使用JBoss Seam Catch 库非常接近。

The bottom line is, there is no standard Java EE prescribed way (currently) to handle servlet exceptions in a centralized fashion similar to what is available in JAX-RS. Since you are using JBoss/RestEASY though, you could utilize the JBoss Seam Catch library to get pretty close.

@HandlesExceptions
public class ExceptionHandler {
    public void handleServletException(
            final @Handles @WebRequest CaughtException<ServletException> caught,
            @Context final HttpServletResponse response) {
        try {
            response.sendError(500, "An error occured");
        } catch (final IOException ioe) {
            System.err.println("Dumb IO Exception: " + ioe);
        }
    }
}

以上说明异常处理程序,如 Seam Catch文档中所述。请注意,图书馆目前处于巨大变化之中,所以您只想作为最后的手段使用它。

The above illustrates an exception handler, as described in the Seam Catch documentation. Note that the library is in massive flux right now, so you will want to utilize it only as a last resort.

这篇关于如何在不向用户显示堆栈跟踪的情况下处理servlet过滤器中的错误状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆