【问题标题】:Exception Listener with JerseyJersey 的异常监听器
【发布时间】:2015-01-23 15:16:57
【问题描述】:

我有一个 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 之类的东西。

【问题讨论】:

    标签: exception jersey listener handler resolver


    【解决方案1】:

    您可以使用 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();
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      我做错了什么?

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

      来自21.1.2. Event Listeners

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-14
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        • 2012-10-03
        相关资源
        最近更新 更多