如何为Spring Data Rest存储库和Querydsl定义请求日期格式

问题描述

简介

比方说,在Spring启动应用程序中,有一个人员存储库接口,它扩展了JpaRepositoryQuerydslPredicateExecutorQuerydslBinderCustomizer,如下所示:

@RepositoryRestResource(path = "persons")
public interface PersonRepository
    extends JpaRepository<Person,Long>,QuerydslPredicateExecutor<Person>,QuerydslBinderCustomizer<QPerson> {

  @Override
  default void customize(QuerydslBindings bindings,QPerson root) {
    bindings.bind(String.class)
        .first((StringPath path,String value) -> (path.eq(value)));
    bindings.bind(LocalDate.class)
        .first((DatePath<LocalDate> path,LocalDate value) -> (path.eq(value)));
  }
}

属于此存储库的Person类(JPA实体)仅包含属性name: StringdateOfBirth: LocalDate

鉴于此,有一些收集端点来查询属于该存储库的(提供的魔术)控制器,如下所示(此处查询名称相同的所有人):

curl "http://localhost:8080/persons?name=John"

此请求已成功处理。

问题

但是如何(集中式)定义查询生日等于某人的所有人的日期格式?

我想这样查询存储库(格式为 yyyy-MM-dd ):

curl "http://localhost:8080/persons?dateOfBirth=1987-12-15"

运行应用程序的系统区域设置设置为 en_US ,因此日期格式类似于 MM / dd / yy 。 (使用此日期格式进行查询,该请求也会成功处理。)

第一次(失败的)思考/尝试

要使用预期的格式,我首先想到的是在Spring Boot的应用程序属性中定义日期格式:

spring.mvc.format.date: yyyy-MM-dd

但是这种方法导致DateTimeParseException说无法解析格式yyyy-MM-dd的日期:

...
Caused by: java.lang.IllegalArgumentException: Parse attempt Failed for value [2020-01-01]
    at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:223) ~[spring-context-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    ... 56 common frames omitted
Caused by: java.time.format.DateTimeParseException: Text '2020-01-01' Could not be parsed at index 4
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046) ~[na:na]
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948) ~[na:na]
    at java.base/java.time.LocalDate.parse(LocalDate.java:428) ~[na:na]
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:69) ~[spring-context-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:46) ~[spring-context-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:217) ~[spring-context-5.2.10.RELEASE.jar:5.2.10.RELEASE]

LocalDate作为参数的手动创建的“常规”存储库资源使用所需的日期格式,因此.../persons/search/findByDateOfBirth=1987-12-15之类的请求已成功处理

一个完整的例子,我创建了一个可执行文件sample project,其中包括一些测试。

解决方法

提供带有 Converter 的自定义 RepositoryRestConfigurer 解决了我的问题,因此可以指定日期格式(Jsr310Converters.StringToLocalDateConverter.INSTANCE 使用 DateTimeFormatter.ISO_DATE):

@Component                                                                                   
public class LocalDateConfiguration implements RepositoryRestConfigurer {                    
                                                                                             
  @Override                                                                                
  public void configureConversionService(ConfigurableConversionService conversionService) {
    conversionService.addConverter(StringToLocalDateConverter.INSTANCE);                 
  }                                                                                        
                                                                                             
}                                                                                            

一般来说:

@Component                                                                                      
public class LocalDateConfiguration implements RepositoryRestConfigurer {                       
                                                                                                
  @Override                                                                                   
  public void configureConversionService(ConfigurableConversionService conversionService) {   
    conversionService.addConverter(new Converter<String,LocalDate>() {                                                                                                                 
      @Override                                                                           
      public LocalDate convert(String source) {                
        // Use any format                           
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");        
        return LocalDate.parse(source,formatter);                                      
      }                                                                                   
    });                                                                                     
  }                                                                                           
                                                                                                
}                                                                                               

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...