我需要在Jersey中创建一个自定义的ExceptionMapper来处理Jackson返回的JsonProcessingException。
Jackson库已经以JsonMappingExceptionMapper.java和JsonParseExceptionMapper.java(link)的形式为此异常提供了ExceptionMapper提供程序。
如果我在“my.package”中为此异常映射器添加新的提供程序,则会得到有关所选提供程序的不可预测的结果。有时它会在“my.package”中选择提供者,有时它会选择Jackson库中的提供者。我用来扫描软件包的代码如下。
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);
此解决方案为我提供了仅使用我指定的提供程序的所需结果。 有没有更正确的方法来实现相同的结果?
答案 0 :(得分:3)
我也遇到过这个问题,在我的情况下,我解决了问题,而不是注册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类是不同的,但可以使用相同的配置。
答案 1 :(得分:0)
我有同样的要求,我必须使用自定义 ExceptionMapper,它为所有 ExceptionMapper<Exception>
类型实现 Exception
。不幸的是,Jersey 默认注册 org.glassfish.jersey.jackson.JacksonFeature
,如果依赖项 jersey-media-json-jackson
存在于类路径中,它会自动注册 JsonParseExceptionMapper
和 JsonMappingExceptionMapper
,并且由于这种默认机制,这些默认的 JSON 异常映射器接收所有与 JSON 相关的异常,这就是不特别为 JSON 异常调用 custom exception mapper
的原因。
幸运的是,Jersey 2.29.1 添加了对注册 JacksonFeature 的支持,而无需异常处理程序。链接 feature request link,code changes。
因此我们必须通过排除以下异常映射器来覆盖默认的 JacksonFeature
@Provider
public class ApplicationInitializer extends ResourceConfig {
public ApplicationInitializer() {
register(JacksonFeature.withoutExceptionMappers());
}
}