Есть ли лучший способ переопределить MappingJackson2HttpMessageConverter по умолчанию, используемый RestClient в Springboot

Мне нужно переопределить зависимость ObjectMapper по умолчанию (и ее конфигурации по умолчанию) MappingJackson2HttpMessageConverter при использовании класса RestClient Springboot.

Не каждый сторонний API, с которым я взаимодействую, соответствует конфигурации по умолчанию, которую, похоже, навязывает Springboot.

Мне удалось успешно переопределить значение по умолчанию ObjectMapper с помощью следующего кода, но:

Мне интересно, есть ли лучший и более очевидный способ добиться этого.

Мне кажется странным, что изменить значение по умолчанию ObjectMapper, используемое RestClient, так сложно.


    private final ObjectMapper objectMapper;

    public RestClientConfig(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Bean("torii")
    public RestClient toriiApi() {
        return RestClient.builder()
                .messageConverters(this::initMessageConverters)
                .baseUrl(toriiApiHost)
                .defaultHeader("Authorization", generateBasicAuthHeaderValue(torriApiBasicAuthUser, torriApiBasicAuthPassword))
                .defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                .defaultHeader("Accepted", MediaType.APPLICATION_JSON_VALUE)
                .build();
    }

    private void initMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        AtomicInteger counter = new AtomicInteger();
        AtomicReference<Integer> jacksonConvertIndex = new AtomicReference<>();
        messageConverters.forEach(httpMessageConverter -> {
            if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
                jacksonConvertIndex.set(counter.get());
            }
            counter.getAndIncrement();
        });
        messageConverters.remove(jacksonConvertIndex.get().intValue());
        messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
    }

В вашем фрагменте вы передаете ObjectMapper в toriiApi(), чтобы не использовать его, а затем в initMessageConverters() используется необъявленная переменная objectMapper... Непонятно, что вы пытались.

dani-vta 01.06.2024 09:05

Ты прав. ObjectMapper, передаваемый в toriiApi(), не использовался. Я передаю правильно настроенный objectMapper, который хочу использовать, через конструктор (и добавил этот код в свой вопрос).

user1530263 01.06.2024 21:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете просто установить objectMapper на существующий MappingJackson2HttpMessageConverter, поскольку у него есть публичный сеттер, унаследованный от AbstractJackson2HttpMessageConverter:

private void initMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        messageConverters.forEach(httpMessageConverter -> {
            if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter jacksonConverter) {
                jacksonConverter.setObjectMapper(objectMapper);
            }
        });
    }

Помимо этой настройки, я думаю, что это подходящее использование API в вашей ситуации, и я предполагаю, что вы хотите сохранить все конвертеры сообщений по умолчанию и изменить только MappingJackson2HttpMessageConverter - параметр на RestClient.Builder#messageConverters называется configurer, так что кажется, что это ожидается, что список будет изменен. В официальной документации также рекомендуется использовать метод messageConverters:

По умолчанию RestClient и RestTemplate регистрируют все встроенные преобразователи сообщений, в зависимости от доступности базовых библиотек в пути к классам. Вы также можете настроить использование преобразователей сообщений явно, используя метод messageConverters() в компоновщике RestClient или через свойство messageConverters объекта RestTemplate.

И это особенно советует в отношении MappingJackson2HttpMessageConverter:

Если вам нужен дополнительный контроль (в случаях, когда для определенных типов необходимо предоставить собственные сериализаторы/десериализаторы JSON), вы можете внедрить собственный ObjectMapper через свойство ObjectMapper.

Возможно, вы предпочтете использовать перегрузку RestClient.builder(RestTemplate) и вместо этого установить messageConverters в RestTemplate, но если вы хотите сохранить функциональность использования слегка измененного списка по умолчанию, вам придется делать то же самое с messageConverters в RestTemplate. Если вас не волнует сохранение остальных MessageConverters, вы можете использовать RestTemplate с нужным вам единственным MappingJackson2HttpMessageConverter.

Спасибо. Установка правильно настроенного ObjectMapper на существующий конвертер работает на 100% и проще, чем мой первоначальный подход.

user1530263 01.06.2024 21:56

Другие вопросы по теме