@EnableWebMvc показывает дату в формате массива

#java #spring #spring-boot #spring-mvc #spring-rest

#java #весна #весенняя загрузка #spring-mvc #весна-отдых

Вопрос:

У нас было два приложения при загрузке spring. Один был основан на spring rest api, а второй — на spring MVC.

Мы отключили оба приложения по некоторым деловым причинам, поскольку контекст был одинаковым, и все работает нормально, кроме java.time.Форматирование LocalDateTime, которое автоматически выполняется spring в rest API. ранее он форматировал LocalDateTime как «2018-08-30T18:13:24», но после слияния он отображается как [ 2018, 08, 30, 18, 13, 24 ],

Я обнаружил, что виновником является аннотация @EnableWebMvc, но после удаления этой аннотации веб-страницы mvc не работают.

Что я должен сделать, чтобы отображение даты в формате ISO (String) и просмотр страниц распознавателя и jsp работали нормально?

Пожалуйста, помогите, спасибо.

Комментарии:

1. Я потратил почти целый день, просматривая различные варианты конфигурации Jackson, и ничего не получалось. К счастью, я наткнулся на ваш пост и действительно @EnableWebMvc был виновником.

Ответ №1:

Все говорят, что виновником является @EnableWebMvc. Но никто не говорит с WebMVC, как решить эту проблему.

Итак, чтобы ответить на вопрос, да, есть способ решить эту проблему, не удаляя @EnableWebMvc.

Прежде чем перейти к ответу, давайте разберемся в нескольких концепциях:

  • HttpMessageConverters -> Это те, которые преобразуют объекты Java из и в JSON / XML
  • По умолчанию Spring boot добавит следующие конвертеры:
    1. ByteArrayHttpMessageConverter
    2. StringHttpMessageConverter
    3. ResourceHttpMessageConverter
    4. SourceHttpMessageConverter
    5. FormHttpMessageConverter
    6. Jaxb2RootElementHttpMessageConverter
    7. MappingJackson2XmlHttpMessageConverter
    8. MappingJackson2HttpMessageConverter
  • Итак, всякий раз, когда мы преобразуем объект Java в JSON, spring просматривает этот список преобразователей один за другим по порядку и выбирает соответствующий для преобразования
  • Теперь, если мы добавим наш пользовательский MappingJackson2HttpMessageConverter в этот список в качестве последнего элемента, spring не попадет в него, потому что перед достижением нашего конвертера (9-й элемент) есть конвертер по умолчанию с 7-м индексом
  • Итак, чтобы решить эту проблему, нам нужно удалить MappingJackson2HttpMessageConverte по умолчанию и добавить наш пользовательский конвертер
 @EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//        Remove the default MappingJackson2HttpMessageConverter
        converters.removeIf(converter -> {
            String converterName = converter.getClass().getSimpleName();
            return converterName.equals("MappingJackson2HttpMessageConverter");
        });
//        Add your custom MappingJackson2HttpMessageConverter
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
        WebMvcConfigurer.super.extendMessageConverters(converters);
    }
}
  

Примечание: Пожалуйста, не используйте configureMessageConverters() вместо extendMessageConverters() из WebMvcConfigurer, потому что метод configure удалит все существующие конвертеры, которые будут установлены по умолчанию.

Надеюсь, это поможет кому-то вроде меня, кто потратил несколько часов на отладку проблемы 🙂

Комментарии:

1. Снимаю шляпу перед вами и вашим профессиональным и научным объяснением. После нескольких часов борьбы это, безусловно, идеальное решение для одного выстрела

Ответ №2:

Если вы используете Jackson в качестве вашего JSON <-> POJO mapper, вы можете установить следующие свойства:

 spring:
  jackson:
    date-format: yyyy-MM-dd'T'hh:mm:ss
    serialization:
      write-dates-as-timestamps: false
  

spring.jackson.serialization.write-dates-as-timestamps по умолчанию true используется значение , которое сериализуется LocalDateTime как массив, подобный тому, который вы показываете.

Для более детального управления вы также можете аннотировать поля даты и времени следующим образом:

 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'hh:mm:ss")
private LocalDateTime datetime;
  

Он имеет приоритет над указанным выше свойством.

Взгляните на другие связанные с JSON свойства Spring Boot здесь: https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#json-properties

Комментарии:

1. Работает только этот @JsonFormat, но я не хочу переходить к каждому dto и делать это. Я хочу сделать это с помощью централизованного способа.

2. Вы определили свой собственный ObjectMapper компонент? Если это так, то это свойство не будет работать, но вы все равно можете установить эту конфигурацию в вашем ObjectMapper с objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) помощью .

Ответ №3:

Для тех, кто все еще сталкивается с проблемой, @EnableWebMVC это, безусловно, виновник, поскольку он отключает поведение автоматической настройки Web MVC по умолчанию в пользу вашего.

Об этом говорится в справочной документации Spring Boot:

Автоматическая настройка Spring MVC

Если вы хотите получить полный контроль над Spring MVC, вы можете добавить свой собственный @Configuration с аннотацией @EnableWebMvc

Однако вы можете добавить пользовательскую конфигурацию без потери поведения автоматической настройки по умолчанию.

Если вы хотите сохранить эти настройки Spring Boot MVC и сделать больше настроек MVC (перехватчики, форматеры, контроллеры просмотра и другие функции), вы можете добавить свой собственный класс @Configuration типа WebMvcConfigurer, но без @EnableWebMvc него.

Тем не менее, удаление @EnableWebMvc должно работать просто отлично.