Как зарегистрировать пользовательские конвертеры в spring загрузке?

Я пишу приложение, используя spring -boot-starter-jdbc (v1.3.0).

Проблема, с которой я встречалась: экземпляр BeanPropertyRowMapper терпит неудачу, поскольку он не может преобразовать из java.sql.Timestamp в java.time.LocalDateTime.

Чтобы скопировать эту проблему, я реализовал org.springframework.core.convert.converter.Converter для этих типов.

public class TimeStampToLocalDateTimeConverter implements Converter<Timestamp, LocalDateTime> {

    @Override
    public LocalDateTime convert(Timestamp s) {
        return s.toLocalDateTime();
    }
}

Мой вопрос: Как сделать доступным TimeStampToLocalDateTimeConverter для BeanPropertyRowMapper.

Более общий вопрос, как я могу зарегистрировать свои конвертеры, чтобы сделать их доступными в системе?

Следующий код приводит нас к NullPointerException на этапе инициализации:

private Set<Converter> getConverters() {
    Set<Converter> converters = new HashSet<Converter>();
    converters.add(new TimeStampToLocalDateTimeConverter());
    converters.add(new LocalDateTimeToTimestampConverter());

    return converters;
}

@Bean(name="conversionService")
public ConversionService getConversionService() {
    ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
    bean.setConverters(getConverters()); 
    bean.afterPropertiesSet();
    return bean.getObject();
}    

Спасибо.

Ответ 1

Я предлагаю использовать @Autowired и соответствующий механизм впрыска зависимостей spring для использования одного экземпляра ConversionService во всем приложении. ConversionService будет создан в конфигурации.

Все конвертеры, доступные для широкого применения, получают аннотацию (например, @AutoRegistered). При запуске приложения @Component FormatterRegistrar (само название типа немного вводит в заблуждение, да, это "... Регистратор", поскольку он регистрирует. И @Component, поскольку он полностью spring управляется и требует инъекции зависимостей), получит @AutoRegistered Список всех аннотированных преобразователей.

Смотрите эту тему для конкретных деталей реализации. Мы используем этот механизм в рамках нашего проекта, и он работает как шарм.

Ответ 2

Попытка добавить

@Converter(autoApply = true)

Его нужно разместить над классом конвертора. Это работает для меня, если для взаимодействия с БД необходим локальный конвертер.

@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {

    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
      return (locDate == null ? null : Date.valueOf(locDate));
    }

    @Override
    public LocalDate convertToEntityAttribute(Date sqlDate) {
      return (sqlDate == null ? null : sqlDate.toLocalDate());
    }
}

Это теперь применяется автоматически при взаимодействии с БД.

Ответ 3

org.springframework.web.servlet.config.annotation.WebMvcConfigurer или любая другая его реализация является одним из основных мест для любой настройки в проекте весенней загрузки. Он предлагает различные методы для вашего конвертера.

Просто создайте новый конвертер, расширяя org.springframework.core.convert.converter.Converter<S, T>. Затем зарегистрируйте его в Spring с помощью метода переопределения классов org.springframework.web.servlet.config.annotation.WebMvcConfigurer.addFormatters(FormatterRegistry)

Обратите внимание, что существуют и другие типы конвертеров, которые в основном начинаются с ConditionalConverter.