簡體   English   中英

在Spring Boot和ElasticSearch中使用Instant,LocalDateTime和ZonedDateTime

[英]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數據格式?

我嘗試了以下方法:

  1. 自定義對象映射器,如下所示:

     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); } } 
  2. 在對象映射器中添加以下內容:

     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);
}

這應該注入你CustomEntityMapperJestResultsMapper ,這又注入JestElasticSearchTemplate框架使用。

CustomEntityMapper您可以自動裝配默認的ObjectMapper (它將自動添加JavaTimeModule ),也可以自行配置一個。

設法使其與Spring Boot 2.1.4和Spring Data Jest一起使用。 這是我所做的:

  1. 域對象示例:

     @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 } 
  2. 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); } } } 
  3. ElasticSearch中的結果:

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM