当前位置: 首页 > 面试题库 >

泽西岛…如何记录所有异常,但仍然调用ExceptionMappers

廖君昊
2023-03-14
问题内容

我有点束缚…要我的蛋糕,也要吃。

我想记录我的应用程序引发的 所有 异常。因此,如果有人输入错误的URL,我想将堆栈跟踪记录到SLF4J。

因此,您可能会想,“嘿,这很简单,只需实现一个异常映射器并记录异常。”所以我做了:

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时,他们会看到500错误,而不是404错误。有人猜测返回null会在链处理程序中传播异常,但是Jersey并没有这样做。实际上,它提供的信息很少,为什么会选择一个处理程序而不是另一个处理程序…

有没有人遇到过这个问题,您是如何解决的?


问题答案:

返回正确的http状态代码,您的异常映射器可能看起来像这样:

@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();            
    }
}

也听起来您对级联异常映射器感兴趣,但是根据规范,这是不可能的:

JAX-RS 2.0规范,第4.4章

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

当资源类或提供程序方法引发异常时,存在一个异常映射提供程序,则匹配提供程序用于获取Response实例。处理结果响应,就像Web资源方法已返回响应一样,请参阅第3.3.3节。特别是,必须使用第6章中定义的ContainerResponse过滤器链来处理映射的Response。

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



 类似资料:
  • 我有点束缚...想要我的蛋糕,也吃了它。 我想记录我的应用程序抛出的所有异常。因此,如果有人点击了错误的URL,我想将堆栈跟踪记录到SLF4J。 所以你可能会想,‘嘿,这很简单,只需实现一个exceptionmapper并记录异常即可。“所以我做了: 如果您这样做,当有人键入错误的URL时,他们得到的不是404个错误,而是500个错误。有人猜测返回null会将异常传播到链处理程序中,但Jersey

  • 问题内容: 我有一个Jersey REST API,并且正在使用来处理授权。我还在所有端点上使用,以便我的API可以处理数千个并发请求。 我的授权过滤器命中了一个远程服务,但是当运行过滤器时,Jersey尚未将当前线程添加到它的内部,因此我完全失去了异步的好处。 我可以告诉Jersey我希望这是异步的吗? 这是一个示例资源: 更新 刚刚收到泽西队球员的回音,从2.7开始,这是不可能的。只有资源方法

  • 我目前使用的是球衣 我现在要做的是设置泽西,这样当查询参数进来时(比如缩进),我可以告诉Jackson以“更漂亮的格式,也就是缩进”序列化JSON。您可以通过使用SerializationConfig.Feature.INDENT_OUTPUT配置JSON映射器来轻松地告诉Jackson这样做。 问题是,我如何在每个请求的基础上获取一个queryparam并使用它来修改Jackson的输出?

  • 问题内容: 有没有办法在Jersey中进行全局异常处理?我希望有一种方法可以将其放置在实际调用资源的地方,而不是单个资源具有try / catch块,然后调用某种方法来清理将要发送回客户端的所有异常。这有可能吗?如果是这样,怎么办? 而是在哪里向Jersey Servlet抛出某种Jersey配置的异常: 具有: 异常会被抛出到我可以拦截并从那里调用的东西。 实际上,这仅仅是为了简化Jersey的

  • 我想返回一个临时重定向,使用AsyncACK。 下面的“工作”(因为没有错误),但似乎不是异步的(它一次处理一个请求)。 这应该工作吗?如果我明确需要像https://jersey.github.io/documentation/latest/async.html#d0e9895一样启动一个新线程,返回响应是什么样子的?

  • 我很难理解泽西岛的注入机制。JAX-RS规范(http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005)指出,在应用程序子类、根资源类和提供程序中可以通过@Context进行注入。 我现在有一个在启动时实例化的类,并且有一个在每次请求时调用的方法。在方法内部,我需要访问当前的UriInfo对象。问题是,这个方法不是从我的