0

我有一个 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 服务方法产生的所有异常?

我想拥有/制作类似 Spring 的 HandlerExceptionResolver 的东西。

4

2 回答 2

3

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

这是我为 ConstraintViolations 所做的示例,但这可以是 Exception 类型的异常映射器。你可以检查异常的类型并做相应的事情。在 toResponse 中,您可以实现一个 notfiyEmail 方法,该方法可以将堆栈跟踪和消息发送到电子邮件地址,或者记录我过去做过的 jira 票证。请注意,您需要在顶部添加 @Provider 并告诉您的其余 Application/ResourceConfig 扫描该类的包。或者,您可以使用 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();
    }
}
于 2015-01-23T19:18:25.667 回答
0

...当发生异常时,我没有得到 ON_EXCEPTION,而是 START。

我究竟做错了什么?

您需要从 START 事件中返回 RequestEventListener 的实例,而不是返回 null,以便告诉 Jersey 继续为请求触发事件。

21.1.2 开始。事件监听器

每次收到新请求时,Jersey 运行时都会调用第二个方法 onRequest。传递给该方法的请求事件类型始终为 START。如果您想侦听新请求的任何其他请求生命周期事件,您应该返回一个处理该请求的 RequestEventListener 实例。

有关记录异常事件的示例,请参阅https://stackoverflow.com/a/33271754/5473824 。

于 2015-10-22T01:09:56.813 回答