你可以责怪JacksonFeature
如果JacksonJaxbJsonProvider 未注册,JacksonFeature 为 Jackson 异常注册默认异常映射器。而这正是你不想要的。
相关部分见source code:
// Register Jackson.
if (!config.isRegistered(JacksonJaxbJsonProvider.class)) {
// add the default Jackson exception mappers
context.register(JsonParseExceptionMapper.class);
context.register(JsonMappingExceptionMapper.class);
...
}
Spring Boot 注册了JacksonFeature
Spring Boot 的 JerseyAutoConfiguration 类将注册 JacksonFeature 如果它在类路径上。相关部分见source code:
@ConditionalOnClass(JacksonFeature.class)
@ConditionalOnSingleCandidate(ObjectMapper.class)
@Configuration
static class JacksonResourceConfigCustomizer {
...
@Bean
public ResourceConfigCustomizer resourceConfigCustomizer(
final ObjectMapper objectMapper) {
addJaxbAnnotationIntrospectorIfPresent(objectMapper);
return (ResourceConfig config) -> {
config.register(JacksonFeature.class);
config.register(new ObjectMapperContextResolver(objectMapper),
ContextResolver.class);
};
}
...
}
解决方法
作为一种解决方法,您可以注册 JacksonJaxbJsonProvider,然后注册您的自定义异常映射器(或者只需使用 @Provider 对其进行注释以让 Jersey 自动发现):
@Component
public class OrderServiceResourceConfig extends ResourceConfig {
public OrderServiceResourceConfig() {
packages("com.rmn.gfc.common.providers");
register(JacksonJaxbJsonProvider.class);
// Register other providers
}
}
查看文档中关于 JacksonJaxbJsonProvider 的内容:
JSON 内容类型提供程序自动配置为使用 Jackson 和 JAXB 注释(按优先级顺序)。其他功能与JacksonJsonProvider 相同。
替代解决方案
或者,您可以摆脱 jersey-media-json-jackson 工件并改用 jackson-jaxrs-json-provider。这样,您将摆脱JacksonFeature,然后您可以注册自己的异常映射器。
在answer中提到过。
似乎是正确的解决方案
请参阅JAX-RS 2.1 specification 中的以下引用:
4.1.3 优先事项
应用程序提供的提供程序使开发人员能够扩展和自定义 JAX-RS 运行时。因此,如果需要单个提供程序,则必须始终首选应用程序提供的提供程序而不是预打包的提供程序。
应用程序提供的提供者可以用@Priority 注释。如果两个或多个提供者是某个任务的候选者,则选择具有最高优先级的提供者:最高优先级被定义为
在这种情况下使用 最低 值。即@Priority(1) 高于@Priority(10)。如果两个或多个提供者符合条件并且具有相同的优先级,则以依赖于实现的方式选择一个。
所有应用程序提供的提供程序的默认优先级是javax.ws.rs.Priorities.USER。过滤器和拦截器的优先级一般规则是不同的,因为这些提供程序是收集的
成链。
正如 Kysil Ivan 的 answer 中所指出的,编写您自己的异常映射器并为其赋予高优先级,例如 1。如果您使用自动发现,只需使用 @Provider 和 @Priority 对其进行注释即可。
@Provider
@Priority(1)
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
...
}
如果你手动注册你的提供者,你可以give your provider a binding priority:
@ApplicationPath("/")
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(JsonParseExceptionMapper.class, 1);
}
}