2017-07-07 142 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