Jersey的异常监听器

时间:2015-01-23 15:16:57

标签: exception jersey listener handler resolver

我有一个泽西(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。

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:0)

  

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

     

我做错了什么?

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

来自21.1.2. Event Listeners

  

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

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