Jersey ...如何记录所有异常,但仍然调用ExceptionMappers [英] Jersey... how to log all exceptions, but still invoke ExceptionMappers

查看:471
本文介绍了Jersey ...如何记录所有异常,但仍然调用ExceptionMappers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点束缚......想要我的蛋糕并吃掉它。

I'm in a little bit of bind... want my cake and to eat it too.

我想记录所有我的应用程序抛出异常。因此,如果某人遇到错误的URL,我想将堆栈跟踪记录到SLF4J。

I want to log all exceptions my application throws. So if someone hits an incorrect URL, i want to log the stack trace to SLF4J.

所以你可能在想,'嘿,这很容易,只需实现异常映射器,记录异常。所以我做了:

So you're probably thinking, 'hey thats easy, just implement an exceptionmapper and log the exception." So I did:

public class RestExceptionMapper implements ExceptionMapper<java.lang.Exception> {
    private static final Logger log = LoggerFactory.getLogger(RestExceptionMapper.class);

    /**
     * {@inheritDoc}
     */
    @Override
    public Response toResponse(Exception exception) {
        log.error("toResponse() caught exception", exception);
        return null;
    }
}

如果这样做,当有人输入错误的URL时,而不是404错误,他们会得到500错误。返回null会将异常传播到链处理程序中,但Jersey不会这样做。它实际上提供了很少的信息,为什么它会选择一个处理程序而不是另一个。 ..

If you do this, instead of 404 errors when someone types a wrong URL in, they get a 500 error. One would guess returning null would propagate the exception down the chain handlers, but Jersey doesn't do that. It actually provides very little info why it would choose one handler over another...

有没有人遇到过这个问题,你是怎么解决的?

Has anyone ran into this problem and how did you solve it?

推荐答案

要返回正确的http状态代码,您的异常映射器可能如下所示:

To return the correct http status code, your exception mapper could look something like this:

@Provider
public class RestExceptionMapper implements ExceptionMapper<Throwable>
{
    private static final Logger log = LoggerFactory.getLogger(RestExceptionMapper.class);

    @Override
    public Response toResponse(Throwable exception)
    {
        log.error("toResponse() caught exception", exception);

        return Response.status(getStatusCode(exception))
                .entity(getEntity(exception))
                .build();
    }

    /*
     * Get appropriate HTTP status code for an exception.
     */
    private int getStatusCode(Throwable exception)
    {
        if (exception instanceof WebApplicationException)
        {
            return ((WebApplicationException)exception).getResponse().getStatus();
        }

        return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
    }

    /*
     * Get response body for an exception.
     */
    private Object getEntity(Throwable exception)
    {
        // return stack trace for debugging (probably don't want this in prod...)
        StringWriter errorMsg = new StringWriter();
        exception.printStackTrace(new PrintWriter(errorMsg));
        return errorMsg.toString();            
    }
}

此外,您似乎对级联异常映射器感兴趣,但根据规范,这是不可能的:

Also it sounds like you are interested in cascading exception mappers, but according to the spec this isn't possible:

JAX-RS 2.0规范,第4.4章

异常映射提供程序将已检查或运行时异常映射到Response实例。异常
映射提供程序实现ExceptionMapper接口,可以使用
@Provider进行注释以进行自动发现。当选择异常映射提供程序来映射异常时,
实现必须使用其泛型类型是异常的最近超类的提供者。

"Exception mapping providers map a checked or runtime exception to an instance of Response. An exception mapping provider implements the ExceptionMapper interface and may be annotated with @Provider for automatic discovery. When choosing an exception mapping provider to map an exception, an implementation MUST use the provider whose generic type is the nearest superclass of the exception.

当资源时class或provider方法抛出一个异常映射
提供者,匹配的提供者用于获取Response实例。生成的Response处理
,好像web资源方法返回了Response ,见3.3.3节。特别是映射的
必须使用第6章中定义的ContainerResponse过滤器链处理响应。

When a resource class or provider method throws an exception for which there is an exception mapping provider, the matching provider is used to obtain a Response instance. The resulting Response is processed as if a web resource method had returned the Response, see Section 3.3.3. In particular, a mapped Response MUST be processed using the ContainerResponse filter chain defined in Chapter 6.

为避免可能无限循环,在处理$ b期间必须使用单个异常映射器$ b请求及其相应的响应。在处理先前从异常映射的响应时,JAX-RS实现绝不能尝试映射抛出的异常
。相反,这个例外必须按照第3.3.4节中的步骤3和4所述处理

To avoid a potentially infinite loop, a single exception mapper must be used during the processing of a request and its corresponding response. JAX-RS implementations MUST NOT attempt to map exceptions thrown while processing a response previously mapped from an exception. Instead, this exception MUST be processed as described in steps 3 and 4 in Section 3.3.4."

这篇关于Jersey ...如何记录所有异常,但仍然调用ExceptionMappers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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