Jersey 的异常侦听器

Exception Listener with Jersey

我有一个 Jersey (2.14) 应用程序,它工作正常。我在那里有一些服务 运行。现在我想配置 ServletContainer,这样任何未捕获的异常都应该被拦截并记录或通过电子邮件发送到某处。

我已经有一个 ApplicationEventListener 的实现和一个用于生成异常的测试端点。

这是应该生成异常的方法(这是有效的:-):

@GET
@Path(TEST_EXCEPTION)
public String testException(@Context final ServletContext context) {
    String s = null;
    int size = 0;
    if (System.nanoTime() % 10 != 0) {
        s = null;
    } else {
        s = "No exception will occur";
    }
    size = s.length();
    return Integer.toString(size) + ":" + s;
}

这就是我的 ApplicationEventListener 的实现:

public class MyApplicationEventListener implements ApplicationEventListener {
    private transient volatile int count = 0;
    private int exceptions = 0;

    @Override
    public void onEvent(final ApplicationEvent applicationEvent) {
        ApplicationEvent.Type type = applicationEvent.getType();
    }

    @Override
    public RequestEventListener onRequest(final RequestEvent requestEvent) {
        RequestEvent.Type type = requestEvent.getType();
        if (type == RequestEvent.Type.ON_EXCEPTION) {
            exceptions++;
        }
        count++;
        return null;
    }
}

这是我 web.xml 中的配置:

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com....rest</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            com....filter.MyApplicationEventListener
        </param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.tracing</param-name>
        <param-value>ALL</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

onEvent() 和 onRequest() 都被调用了,但是当异常发生时,我没有得到 ON_EXCEPTION,而是 START。

我做错了什么?或者我怎样才能得到由我的 Jersey 服务的方法产生的所有异常?

我想要 have/make 类似于 Spring 的 HandlerExceptionResolver。

您可以使用 ExceptionMapper 轻松完成此操作。如果发生异常,您仍然应该将响应发送回客户端。但在这里您还可以发送电子邮件消息或记录工单等。

这是我为 ConstraintViolations 做的一个示例,但这可以是 Exception 类型的异常映射器。您可以检查异常的类型并相应地做一些事情。在 toResponse 中,您可以实现一个 notfiyEmail 方法,该方法可以将堆栈跟踪和消息发送到一个电子邮件地址,或者记录一个我过去做过的 jira 票证。请注意,尽管您需要在顶部添加 @Provider 并告诉您的其他 Application/ResourceConfig 扫描包中的此 class。或者,您可以使用 ResourceConfig 手动注册它。

@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    private static final Logger logger = Logger.getLogger(ConstraintViolationExceptionMapper.class.getName());

    public Response toResponse(ConstraintViolationException exception) {            
            final int violationCount = exception.getConstraintViolations().size();

            ConstraintViolation<?>[] constraintViolations = exception.getConstraintViolations().toArray(
                    new ConstraintViolation<?>[violationCount]);
            Violation[] violations = new Violation[exception.getConstraintViolations().size()];

            for (int i = 0; i < violationCount; i++) {
                ConstraintViolation<?> cv = constraintViolations[i];
                Violation violation = new Violation(cv.getPropertyPath().toString(), cv.getMessage());
                violations[i] = violation;
            }

            ConstraintErrorResponse responseEntity = new ConstraintErrorResponse();
            responseEntity.setViolations(violations);

            logger.info("Seinding exception response");
            return Response.status(Response.Status.BAD_REQUEST).entity(responseEntity).build();
    }
}

...when an Exception happens, I don't get a ON_EXCEPTION, but a START.

What am I doing wrong?

您需要 return 来自 START 事件的 RequestEventListener 实例,而不是 returning null,以便告诉 Jersey 继续为请求触发事件。

来自 21.1.2. Event Listeners :

The second method onRequest is invoked by Jersey runtime every time a new request is received. The request event type passed to the method is always START. If you want to listen to any other request lifecycle events for the new request, you are expected to return an instance of RequestEventListener that will handle the request.

有关记录异常事件的示例,请参阅 。