[英]Using Instant, LocalDateTime and ZonedDateTime with Spring Boot and ElasticSearch
我正在將Spring Boot 2.1.4和Spring Data Jest與ElasticSearch結合使用。 我最初將Java Date用於帶有以下注釋的某些屬性:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
將其保存到ElasticSearch中,如下所示:
"creationDate": "2019-04-10T14:49:05.672+0000"
現在,我正在從Date遷移到LocalDateTime和ZonedDateTime。 現在將數據保存到ElasticSearch時,將保存以下屬性:
"creationDate": {
"dayOfYear": 123,
"dayOfWeek": "FRIDAY",
"month": "MAY",
"dayOfMonth": 3,
"year": 2019,
"monthValue": 5,
"hour": 11,
"minute": 54,
"second": 12,
"nano": 238000000,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
我需要做些什么來更改它,以便獲得與LocalDateTime和ZonedDateTime相同的ElasticSearch數據格式?
我嘗試了以下方法:
自定義對象映射器,如下所示:
public class CustomEntityMapper implements EntityMapper { private final ObjectMapper objectMapper; public CustomEntityMapper(ObjectMapper objectMapper) { this.objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); objectMapper.registerModule(new CustomGeoModule()); objectMapper.registerModule(new JavaTimeModule()); } @Override public String mapToString(Object object) throws IOException { return objectMapper.writeValueAsString(object); } @Override public <T> T mapToObject(String source, Class<T> clazz) throws IOException { return objectMapper.readValue(source, clazz); } }
在對象映射器中添加以下內容:
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
我將要出錯的任何幫助或指針將不勝感激。
這是因為spring-data-jest
使用DefaultEntityMapper
(Spring Data的一部分),它創建了自己的ObjectMapper
,而不使用Spring引導提供的對象。 這可以從這個相關問題中看出。
通過定義自己的EntityMapper
(例如CustomEntityMapper
,您在解決方案上將走上正確的道路。 但是, spring-data-jest
將此映射器包裝到名為DefaultJestResultsMapper
的類中,然后該類由名為JestElasticsearchTemplate
的bean使用。
因此,可能您應該執行以下操作:
@Bean
public JestResultsMapper resultMapper(CustomEntityMapper entityMapper) {
return new DefaultJestResultsMapper(entityMapper);
}
@Bean
public JestElasticSearchTemplate template(JestClient client, JestResultsMapper resultsMapper) {
return new JestElasticSearchTemplate(client, resultsMapper);
}
這應該注入你CustomEntityMapper
成JestResultsMapper
,這又注入JestElasticSearchTemplate
框架使用。
在CustomEntityMapper
您可以自動裝配默認的ObjectMapper
(它將自動添加JavaTimeModule
),也可以自行配置一個。
設法使其與Spring Boot 2.1.4和Spring Data Jest一起使用。 這是我所做的:
域對象示例:
@Document(indexName = "datetest") public class DateTest { @Id private String id; @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ", timezone = "UTC") private Instant instant = Instant.now(); @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ") private ZonedDateTime zonedDateTime = ZonedDateTime.now(); @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSS") private LocalDateTime localDateTime = LocalDateTime.now(); // getters/setters }
ElasticSearch / JEST配置:
@Configuration public class ESConfig { @Bean public EntityMapper getEntityMapper() { return new CustomEntityMapper(); } @Bean @Primary public ElasticsearchOperations elasticsearchTemplate(final JestClient jestClient, final ElasticsearchConverter elasticsearchConverter, final SimpleElasticsearchMappingContext simpleElasticsearchMappingContext, EntityMapper mapper) { return new JestElasticsearchTemplate(jestClient, elasticsearchConverter, new DefaultJestResultsMapper(simpleElasticsearchMappingContext, mapper)); } public class CustomEntityMapper implements EntityMapper { private final ObjectMapper objectMapper; public CustomEntityMapper() { objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); objectMapper.registerModule(new CustomGeoModule()); objectMapper.registerModule(new JavaTimeModule()); } @Override public String mapToString(Object object) throws IOException { return objectMapper.writeValueAsString(object); } @Override public <T> T mapToObject(String source, Class<T> clazz) throws IOException { return objectMapper.readValue(source, clazz); } } }
ElasticSearch中的結果:
希望這可以幫助。
根據Spring Boot版本2的此答案 ,就可以從java.time對象生成字符串方面而言,它應該可以立即使用
如果你有
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.4.0
作為依賴關系,在application.properties中的下一行
spring.jackson.serialization.write_dates_as_timestamps=false
因此,剩下的就是將時區表示法添加到默認字符串中,而默認字符串將沒有它。
如果標准格式器對您不起作用,請始終編寫自己的序列化器/解串器,並按此處說明的那樣進行附加
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.