#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 добавит следующие конвертеры:
- ByteArrayHttpMessageConverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter
- FormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
- MappingJackson2XmlHttpMessageConverter
- 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 должно работать просто отлично.