我正在使用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
该方法应该只接受没有时间信息的日期。在这种情况下我不需要这个。我正在使用Spring Data REST工具,因此没有实现该方法。服务器时区是欧洲/罗马,但由于显示的配置,我正在以DB格式存储日期。关于Jackson2ObjectMapperBuilderCustomizer我编辑我的问题添加类,根据https://github.com/spring-projects/spring-boot/issues/4217 – drenda
@drenda你显然需要将客户端发送的字符串转换为日期时间,不管你发送给“findAllWithParameter”。如果您盲目地将客户端发送的字符串传递给该方法,则假设您的所有客户端都来自相同的位置,这显然是错误的。然后是'findAllWithParameter'和DB时间之间的转换问题,你说的是UTC。 如果需要,Spring Data方法可以包含主体。在这种情况下,您需要一个定制存储库。 –
因为使用UTC是最佳做法,所以我的客户(在这种情况下是Angular应用程序)将以UTC格式发送所有日期。所以我认为没有必要为一些应该是相当标准的东西制作很多样板代码。谢谢 – drenda