【问题标题】:Overriding included provider in Jersey覆盖泽西岛中包含的提供程序
【发布时间】:2013-04-13 15:06:57
【问题描述】:

我需要在 Jersey 中创建一个自定义 ExceptionMapper 来处理 Jackson 返回的 JsonProcessingException。

Jackson 库已经以 JsonMappingExceptionMapper.java 和 JsonParseExceptionMapper.java (link) 的形式包含此异常的 ExceptionMapper 提供程序。

如果我在“my.package”中为这个异常映射器添加一个新的提供者,我会得到关于所选提供者的不可预知的结果。有时它会选择“my.package”中的提供者,有时它会选择杰克逊库中的提供者。我用来扫描包的代码如下。

PackgesResourceConfig packagesResourceConfig = new PackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");

建议的解决方案

目前,我通过手动过滤掉 Jackson 库中的提供程序来解决这个问题。但我真正想知道的是,是否有更可接受和支持的方式来做到这一点。

首先我扩展 PackagesResourceConfig。

public class FilteredPackgesResourceConfig extends PackagesResourceConfig {

    private Set<Class<?>> classesToFilter = new HashSet<Class<?>>();

    public FilteredPackgesResourceConfig(String... packages) {
        super(packages);
    }

    public FilteredPackgesResourceConfig(Map<String, Object> props) {
        super(props);
    }

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = super.getClasses();

        if (classes != null && classesToFilter != null) {
            classes.removeAll(classesToFilter);
        }

        return classes;
    }

    public Set<Class<?>> getClassesToFilter() {
        return classesToFilter;
    }

    public void setClassesToFilter(Set<Class<?>> classesToFilter) {
        this.classesToFilter = classesToFilter;
    }
}

这个我使用这个类来过滤掉我不想要的特定提供者。

FilteredPackgesResourceConfig packagesResourceConfig = new FilteredPackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonMappingExceptionMapper.class);       
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonParseExceptionMapper.class);
packagesResourceConfig.setClassesToFilter(classesToFilter);

此解决方案为我提供了仅使用我指定的提供程序的预期结果。 有没有更正确的方法可以达到同样的效果?

【问题讨论】:

标签: java jersey jackson


【解决方案1】:

我也遇到了这个问题,在我的例子中,我通过注册 com.fasterxml.jackson.jaxrs.json 包而不是注册我只注册了我想要的类来解决它,在我的例子中是 com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider

有几种方法可以做到这一点,我是这样使用 web.xml 的:

<servlet>
  <servlet-name>jersey-serlvet</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
         my.own.package
         my.other.package
      </param-value>
  </init-param>
  <init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
      com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider
    </param-value>
  </init-param>
    <init-param>
      <param-name>jersey.config.disableMoxyJson</param-name>
      <param-value>true</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

注意:我使用的是 Jersey 2.0,在 1.x 中,属性名称和 servlet 类不同,但可以使用相同的配置。

【讨论】:

  • com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider 已弃用
【解决方案2】:

我有同样的要求,我必须使用自定义 ExceptionMapper,它为所有 Exception 类型实现 ExceptionMapper&lt;Exception&gt;。不幸的是,如果依赖项 jersey-media-json-jackson 存在于类路径中,Jersey 默认注册 org.glassfish.jersey.jackson.JacksonFeature,而类路径会自动注册 JsonParseExceptionMapperJsonMappingExceptionMapper,并且由于这种默认机制,这些默认 JSON 异常映射器接收所有与 JSON 相关的异常,即原因是 custom exception mapper 没有特别针对 JSON 异常调用。

幸运的是,Jersey 2.29.1 增加了对在没有异常处理程序的情况下注册 JacksonFeature 的支持。链接feature request linkcode changes

因此我们必须通过排除下面的异常映射器来覆盖默认的JacksonFeature

@Provider
public class ApplicationInitializer extends ResourceConfig {
    public ApplicationInitializer() {
        register(JacksonFeature.withoutExceptionMappers());
    }
}

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 2013-06-21
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    相关资源
    最近更新 更多