Пользовательский сопоставитель теней Джексона JsonParseExceptionMapper и JsonMappingExceptionMapper

1

В моем проекте используется Spring Boot + Jersey 2.

Я создал пользовательский сопоставитель Jackson для JsonParseException, но он не получил вызов, вместо этого использовался стандартный Jackson JsonParseExceptionMapper.

Мой пользовательский сопоставитель:

 package com.rmn.gfc.common.providers;
 import ...

 @Provider
 public class JsonParseExceptionHandler implements ExceptionMapper<JsonParseException> { 
    @Override
    public Response toResponse(JsonParseException exception) {
        return Response
                .status(Response.Status.BAD_REQUEST)
                //  entity ...
                .build();
    }
}

Я регистрирую свой картограф следующим образом:

@Component
public class OrderServiceResourceConfig extends ResourceConfig {
    public OrderServiceResourceConfig() {
        packages("com.rmn.gfc.common.providers");
    }
}

Я уверен, что регистрация картографа прекрасна, потому что другие пользовательские mappers из этого пакета работают, но один для JsonParseException скрыт стандартным JsonParseExceptionMapper от Джерси.

Как я могу переопределить стандартный Jackson JsonParseExceptionMapper с моей реализацией?

Теги:
spring-boot
jersey

2 ответа

3

Я нашел решение, которое подходит для меня.
Используйте javax.annotation.Priority на вашем настраиваемом картографе, чтобы он переопределил картографию по умолчанию Джексона, например:

@Provider
@Priority(1)
public class JsonParseExceptionHandler implements ExceptionMapper<JsonParseException> {
    // ...
}

ИЛИ, если вы зарегистрируете компоненты JAX-RS через ResourceConfig, вы можете указать приоритет следующим образом:

public class MyResourceConfig extends ResourceConfig {
    public MyResourceConfig() {
        register(JsonMappingExceptionHandler.class, 1);
        register(JsonParseExceptionHandler.class, 1);
        // ...
    }
}

Нижний номер - самый высокий приоритет.
javax.ws.rs.Priorities имеет определенные предопределенные константы для приоритетов.

  • 0
    Это модное решение!
  • 0
    Какая версия трикотажа?
Показать ещё 3 комментария
2

Вы можете обвинить JacksonFeature

JacksonFeature регистрирует сборщики исключений по умолчанию для исключений Джексона, если JacksonJaxbJsonProvider не зарегистрирован. И это именно то, чего вы не хотите.

См. соответствующие части исходный код:

// Register Jackson.
if (!config.isRegistered(JacksonJaxbJsonProvider.class)) {
    // add the default Jackson exception mappers
    context.register(JsonParseExceptionMapper.class);
    context.register(JsonMappingExceptionMapper.class);
    ...
}

Spring Загрузка регистрирует JacksonFeature

Класс Spring Boot JerseyAutoConfiguration зарегистрирует JacksonFeature, если он находится в пути к классам. См. Соответствующие части исходный код:

@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, чтобы автоматически обнаружить Джерси):

@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, а затем вы сможете зарегистрировать свои собственные механизмы отображения.

Это упоминалось в этом .

То, что кажется правильным решением

Как указано в Kysil Ivan answer, напишите свой собственный блок отображения исключений и придайте ему высокий приоритет, например 1. Если вы используете автоматическое обнаружение, просто комментируйте его с помощью @Provider и @Priority:

@Provider
@Priority(1)
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
    ...
}

Если вы вручную зарегистрируете своего провайдера, вы можете предоставить провайдеру привязывающий приоритет:

@ApplicationPath("/")
public class MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        register(JsonParseExceptionMapper.class, 1);
    }
}
  • 0
    Я не уверен, что регистрация JacksonJaxbJsonProvider является подходящим решением для меня. Я боюсь побочных эффектов. Я хотел бы найти более целенаправленное решение, просто зарегистрировать свой картограф вместо по умолчанию. Благодарю.
  • 1
    @KysilIvan Пожалуйста, смотрите мой ответ снова. Это было обновлено.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню