你能用JAX-RS/Jersey做传统的Servlet过滤吗?

Sha*_*aun 5 java jax-rs jersey java-ee servlet-filters

想象一下,您有一个启动数据库事务的过滤器,处理请求,然后尝试提交事务.

doFilter(...) {
    ...
    transaction.begin();
    filterChain.doFilter(request, response);
    transaction.commit();
}
Run Code Online (Sandbox Code Playgroud)

使用Jersey,有一些问题:

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

    public ContainerRequest过滤器(ContainerRequest请求){...}
    公共ContainerResponse过滤器(ContainerRequest请求,ContainerResponse响应){...}

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

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

drv*_*ijk 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确保事务已关闭,如果没有,则回滚。