使用Spring @RestController和@QuerydslPredicate处理带有ZonedDateTime参数的GET请求

4
我正在创建一个端点,用于接收日期以在服务器端进行一些过滤。代码如下:
@RequestMapping(value = "/invoices", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<List<Invoice>> getAllInvoices(@QuerydslPredicate(root = Invoice.class) Predicate predicate, Pageable pageable) throws URISyntaxException {
    log.debug("REST request to get a page of Invoices");
    Page<Invoice> page = invoiceService.findAll(predicate, pageable);
    HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/invoices");
    return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}

当我尝试使用此网址调用端点时:http://localhost:3000/api/invoices?page=0&size=20&sort=id,asc&sort=id&transactionDate=2016-05-09T22:00:00.000Z&transactionDate=2016-05-17T21:59:59.999Z,会抛出以下异常:
java.time.format.DateTimeParseException: Text '2016-05-09T22:00:00.000Z' could not be parsed at index 10
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) ~[na:1.8.0_91]
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) ~[na:1.8.0_91]
    at java.time.ZonedDateTime.parse(ZonedDateTime.java:597) ~[na:1.8.0_91]
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:80) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:47) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:194) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.convertToPropertyPathSpecificType(QuerydslPredicateBuilder.java:217) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
..... etc etc

解析给定的日期(在ideone.com上)只使用ZonedDateTime对象就可以完成,但是可能还有其它问题。我在SO上找到了这个问题:使用Spring @RestController处理具有ZonedDateTime参数的HTTP GET请求
@RequestMapping(value = "/invoices", params="action", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<List<Invoice>> findInvoices(@RequestParam("dt") @DateTimeFormat(iso=ISO.DATE_TIME) ZonedDateTime dt,Pageable pageable) throws URISyntaxException {
    log.debug("REST request to get a page of Invoices");
    Page<Invoice> result = invoiceRepository.findAllByTransactionDate(dt,pageable);
    HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(result, "/api/invoices");
    return new ResponseEntity<>(result.getContent(), headers, HttpStatus.OK);
}

请求url: localhost:8080/api/invoices?action=search&dt=2016-05-13T15:12:33.658Z 将会得到期望的效果.

显然的区别是对请求参数添加了 @DateTimeFormat(iso=ISO.DATE_TIME)。现在我在想,如何与 QueryDslPredicateBuilder 一起使用?我是否需要以某种方式指定格式?

1个回答

3

当寻找使用querydsl参数绑定的不同方面(使用> x>这种比较),我遇到了以下文章:

Spring Data REST的QueryDSL集成可以用于执行更复杂的查询吗?

其中一个答案提到:

确保为User的dateOfBirth属性添加@DateTimeFormat注释,以便Spring能够正确地将传入的字符串转换为LocalDate实例。

这是我的问题的解决方案。我已经向我的模型添加了@DateTimeFormat注释:

@DateTimeFormat(iso = ISO.DATE_TIME) 
@Column(name = "transaction_date")
private ZonedDateTime transactionDate;

瞧,它能正常工作了。


也许你可以尝试使用全局配置:spring.jackson.date-format: com.fasterxml.jackson.databind.util.ISO8601DateFormat,它可能会产生相同的效果,并且这是实现你所需求的更简单的方法。 - Julio Villane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接