使用Spring Data Rest与QuerydslPredicateExecutor时修改请求URL日期时间格式
刚好我之前处理过类似的场景,给你梳理一下完整的解决方案,既解决日期格式适配问题,又实现忽略时间的精准查询:
1. 完善QuerydslBinderCustomizer的绑定逻辑
你已经写了一部分绑定代码,这里我们补全并优化,确保不管传入的是LocalDateTime还是LocalDate,都能正确匹配当天的所有记录:
public interface ReservationRepository extends Repository<Reservation, Long>, QuerydslPredicateExecutor<Reservation>, QuerydslBinderCustomizer<QReservation> { @Override default void customize(QuerydslBindings bindings, QReservation root) { // 针对created字段的日期查询绑定 bindings.bind(root.created).first((path, value) -> { LocalDateTime startOfDay; LocalDateTime endOfDay; // 处理传入的LocalDateTime类型参数 if (value instanceof LocalDateTime) { LocalDate targetDate = ((LocalDateTime) value).toLocalDate(); startOfDay = targetDate.atStartOfDay(); endOfDay = targetDate.atTime(23, 59, 59, 999999999); } // 处理传入的LocalDate类型参数(更友好的日期格式) else if (value instanceof LocalDate) { startOfDay = ((LocalDate) value).atStartOfDay(); endOfDay = ((LocalDate) value).atTime(23, 59, 59, 999999999); } // 不支持的类型返回null,跳过该条件 else { return null; } // 返回between条件,匹配当天所有时间的记录 return path.between(startOfDay, endOfDay); }); // 可选:只允许查询指定字段,避免不必要的全局查询风险 bindings.excludeUnlistedProperties(true); bindings.including(root.created); } }
关键说明:这里我们把传入的时间/日期转换为目标日期的当天起始时刻和当天结束时刻,确保查询覆盖当天00:00:00到23:59:59.999999999的所有记录,完全忽略时间部分的影响。
2. 配置URL中的日期时间格式支持
Spring Data Rest默认的日期格式可能和你传入的URL参数格式不匹配,我们可以通过两种方式适配:
方式一:实体字段上添加注解
直接在Reservation类的created字段上指定JSON序列化/反序列化的格式:
import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; public class Reservation { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "UTC") private LocalDateTime created = LocalDateTime.now(); // 其他字段、getter和setter方法 }
方式二:全局配置(推荐)
在Spring Boot的配置文件(application.properties或application.yml)中配置全局的日期时间格式:
# 全局日期时间格式 spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss spring.jackson.time-zone=UTC # 禁用时间戳格式,强制使用字符串格式 spring.jackson.serialization.write-dates-as-timestamps=false # 支持Java 8时间类型的序列化/反序列化 spring.jackson.modules=com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
这样配置后,URL中传入的日期时间字符串会被正确解析为LocalDateTime或LocalDate类型。
3. 发起查询请求的示例
配置完成后,你可以通过以下两种方式发起查询:
传入完整的日期时间字符串:
GET /reservations?created=2024-05-20T10:30:00这个请求会查询2024年5月20日当天的所有
Reservation记录,忽略传入的10:30:00时间部分。直接传入日期字符串(如果配置了支持
LocalDate解析):GET /reservations?created=2024-05-20这个请求同样会返回2024年5月20日当天的所有记录。
4. 必要的依赖与配置检查
确保你的项目中已经引入了Querydsl的相关依赖(以Maven为例):
<dependencies> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- Querydsl JPA --> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> </dependency> <!-- Querydsl APT 插件依赖,用于生成Q类 --> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <scope>provided</scope> </dependency> </dependencies>
同时在pom.xml的build部分添加APT插件,用于生成Querydsl的Q类(比如QReservation):
<build> <plugins> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> </plugins> </build>
内容的提问来源于stack exchange,提问作者chaldaean

