2017-07-07 137 views
0

我正在使用Spring Boot 1.5.3,Spring Data REST,Spring JPA,Hibernate。 我在UTC使用服務器中的java.time。*,並且我的客戶也應該以UTC發回日期。 我定製了一下我的REST配置:Spring MVC LocalDate參數格式錯誤

@Configuration 
public class RestConfig extends RepositoryRestConfigurerAdapter { 

@Bean 
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { 
    return new Jackson2ObjectMapperBuilderCustomizer() { 

     @Override 
     public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { 

      jacksonObjectMapperBuilder.serializers(InstantSerializer.INSTANCE); 
      jacksonObjectMapperBuilder.serializers(new ZonedDateTimeSerializer(ISO_FIXED_FORMAT)); 
      jacksonObjectMapperBuilder 
        .serializers(new LocalDateSerializer(new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd").toFormatter())); 
      jacksonObjectMapperBuilder.serializers(new LocalDateTimeSerializer(
        new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").toFormatter())); 
     } 

    }; 
} 

}

我創建存儲庫中的自定義方法:

@Transactional 
@PreAuthorize("isAuthenticated()") 
public interface DailyCodeRepository extends PagingAndSortingRepository<DailyCode, Long> { 


    @Query("SELECT d FROM DailyCode d WHERE (:code IS NULL OR code=:code) AND (:from IS NULL OR date>=:from) AND (:to IS NULL OR date<=:to)") 
    public Page<DailyCode> findAllWithParameter(@Param("code") @RequestParam(value = "code", required = false) String code, 
      @Param("from") @RequestParam(value = "from", required = false) @DateTimeFormat(iso=ISO.DATE) LocalDate from, 
      @Param("to") @RequestParam(value = "to", required = false) @DateTimeFormat(iso=ISO.DATE) LocalDate to, Pageable pageable); 
} 

第一個問題是該方法接受ISO格式只有如果我把註釋@DateTimeFormat(iso=ISO.DATE),否則它選擇我的區域設置(意大利)的格式。我想將其設置爲全局響應(請參閱我的Jackson2ObjectMapperBuilderCustomizer)。

第二個問題是從客戶機發送該日期參數被解釋像前1天,這樣的請求是這樣的:

http://localhost:8080/api/v1/dailyCodes/search/findAllWithParameter?from=2017-07-07&to=2017-07-07 

原因此查詢在數據庫上:

select dailycode0_.`id` as id1_7_, dailycode0_.`created_by` as created_2_7_, dailycode0_.`created_date` as created_3_7_, dailycode0_.`last_modified_by` as last_mod4_7_, dailycode0_.`last_modified_date` as last_mod5_7_, dailycode0_.`sid` as sid6_7_, dailycode0_.`version` as version7_7_, dailycode0_.`code` as code8_7_, dailycode0_.`date` as date9_7_ from `daily_code` dailycode0_ where (null is null or dailycode0_.`code`=null) and ('2017-07-06' is null or dailycode0_.`date`>='2017-07-06') and ('2017-07-06' is null or dailycode0_.`date`<='2017-07-06') limit 20 

所以它查詢1天前,這是錯誤的。我想這是一個時區問題,但我無法弄清楚如何解決這個問題。

這是我的特性相關的部分文件:

spring.mvc.date-format= `yyyy-MM-dd` 
# REST 
spring.data.rest.default-page-size= 20 
spring.data.rest.base-path=/api/v1 
spring.data.rest.enable-enum-translation=true 

#Jackson 

# to avoid an error loading lazy objects 
spring.jackson.serialization.fail-on-empty-beans=false 
spring.jackson.serialization.write-dates-as-timestamps=false 
spring.jackson.mapper.infer-property-mutators=false 
spring.jpa.properties.hibernate.jdbc.time_zone = UTC 

回答

1

您在你的代碼的幾個問題:

第一個問題是,該方法接受ISO格式只

您需要一個OffsetDateTime(不是ZonedDateTime,請閱讀this)和自定義轉換器。閱讀this。從客戶端發送

日期參數解釋像1天

爲什麼之前?什麼時區你解釋這個日期?您的本地時區可能與服務器的不同,可能與客戶端不同。

Jackson2ObjectMapperBuilderCustomizer

這是什麼用的呢?

spring.mvc.date格式= YYYY-MM-DD

這不應該是必要的,而且我不認爲做春季數據進行任何反正。

+0

該方法應該只接受沒有時間信息的日期。在這種情況下我不需要這個。我正在使用Spring Data REST工具,因此沒有實現該方法。服務器時區是歐洲/羅馬,但由於顯示的配置,我正在以DB格式存儲日期。關於Jackson2ObjectMapperBuilderCustomizer我編輯我的問題添加類,根據https://github.com/spring-projects/spring-boot/issues/4217 – drenda

+0

@drenda你顯然需要將客戶端發送的字符串轉換爲日期時間,不管你發送給「findAllWithParameter」。如果您盲目地將客戶端發送的字符串傳遞給該方法,則假設您的所有客戶端都來自相同的位置,這顯然是錯誤的。然後是'findAllWithParameter'和DB時間之間的轉換問題,你說的是UTC。 如果需要,Spring Data方法可以包含主體。在這種情況下,您需要一個定製存儲庫。 –

+0

因爲使用UTC是最佳做法,所以我的客戶(在這種情況下是Angular應用程序)將以UTC格式發送所有日期。所以我認爲沒有必要爲一些應該是相當標準的東西製作很多樣板代碼。謝謝 – drenda