6

假设您有一个过滤器,它启动数据库事务、处理请求,然后尝试提交事务。

doFilter(...) {
    ...
    transaction.begin();
    filterChain.doFilter(request, response);
    transaction.commit();
}

使用 Jersey,有一些问题:

  1. 使用过滤器,Jersey Servlet 容器在执行返回到您的过滤器之前提交/刷新响应。因此,如果提交失败,您不能将返回码修​​改为失败。此外,JAX-RS ExceptionMapper 不会捕获异常。
  2. 使用 ContainerRequestFilter/ContainerResponseFilter。

    public ContainerRequest filter(ContainerRequest request) { ... }
    public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { ... }

这允许异常冒泡到 ExceptionMapper,但将逻辑拆分为 2 个单独的方法/接口。问题是,如果存在未映射到响应的异常,则永远不会调用 ContainerResponseFilter,因此您无法清理。

在 JAX-RS 环境中处理此问题的首选方法是什么?有没有办法配置响应的刷新,或者是否有我忽略的类或接口?

4

1 回答 1

3

对于 JAX-RS/RESTEasy 应用程序,我也一直在研究这一点。在阅读此问题之前我正在考虑的两个选项:

  1. 编写一个ExceptionMapper<Throwable>(或ExceptionMapper<DaoException>使用自定义DaoException)并在其中处理它或在其中处理它,因为处理所有异常ContainerResponseFilter而将被执行。ExceptionMapper<?>
  2. 之前transaction.begin(),检查事务的当前状态,并在需要时回滚。

两种选择都有问题。

  1. 我发现一个ExceptionMapper<Throwable>太宽泛,而ExceptionMapper<DaoException>可能会错过一些其他异常,再次使交易没有清理。
  2. 在下一个请求时回滚事务可能需要很长时间,可能会导致其他事务出现锁定问题。

因此,在阅读了您的问题后,我目前正在考虑:

  • 使用 aContainerRequestFilter启动事务(结合@NameBinding注解构造)。
  • 使用 aContainerResponseFilter提交事务(如果资源方法尚未关闭它)。
  • 使用 aFilter确保事务已关闭,如果没有,则将其回滚。
于 2013-07-16T21:30:59.683 回答