创建时间:2024-10-08
本文适用的依赖版本:
spring-boot-starter-parent:3.3.3
spring-cloud-starter-openfeign:4.1.3
一、场景
在 REST API
的查询接口中,日期查询参数
的格式一般是标准(ISO 8601)的日期字符串,比如:2024-10-04
。常见的查询参数一般为:开始日期(beginDate),结束日期(endDate)。
数据类中日期类型一般使用 LocalDate
或者 Date
,但是远程接口中接收的是字符串类型的日期。在使用OpenFeign调用远程接口时,FeignClient中的查询接口
需要传递日期
类型的查询参数,此时日期参数
的参数类型,应该如何处理?
其中一种方法时,直接将FeignClient中的日期类型定为 String
,然后在调用FeignClient接口的位置,将 LocalDate 或 Date 转为日期字符串。不过这种方法需要每次调用接口前都要做一次转换,比较繁琐,不够简洁,不推荐使用。
另一种是在FeignClient中的接口,使用 LocalDate 或 Date 类型表示日期,然后在实际调用远程接口时,由Feign框架将LocalDate或Date类型转为字符串类型的日期,此时需要使用@DateTimeFormat注解进行日期格式化。下面主要介绍这种方法。
二、@DateTimeFormat格式化日期
FeignClient
使用 @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
修饰日期查询参数,可以将日期类型转为字符串类型的日期。
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
,代表指定的日期格式是 ISO 的日期格式。使用 @DateTimeFormat(pattern = “yyyy-MM-dd”)
,还可以指定其他的日期格式。
package com.example.hello_feign_client.feign.client;
import com.example.hello_common.model.query.LocalDateQuery;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.time.LocalDate;
import java.util.Date;
@FeignClient(contextId = "dateFeignClient",
name = "hello-feign-server",
url = "${service.hello-feign-server.url}",
path = "/date")
public interface DateFeignClient {
@GetMapping("/localDate")
String getDate(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate);
@GetMapping("/localDateQuery")
String getDateQuery(@SpringQueryMap LocalDateQuery localDateQuery);
@GetMapping("/date")
String getDate(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date);
}
调用FeignClient
package com.example.hello_feign_client.web.date.controller;
import com.example.hello_common.model.query.LocalDateQuery;
import com.example.hello_feign_client.feign.client.DateFeignClient;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.Date;
@RestController
@RequestMapping("/date")
@RequiredArgsConstructor
public class DateController {
private final DateFeignClient dateFeignClient;
@GetMapping("/localDate")
public String getDate(@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate) {
return dateFeignClient.getDate(localDate);
}
@GetMapping("/localDateQuery")
public String getDateQuery(LocalDateQuery localDateQuery) {
return dateFeignClient.getDateQuery(localDateQuery);
}
@GetMapping("/date")
public String getDate(@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date) {
return dateFeignClient.getDate(date);
}
}
LocalDateQuery
package com.example.hello_common.model.query;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
@Data
public class LocalDateQuery {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate beginDate;
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate endDate;
}
远程接口
package com.example.hello_feign_server.web.date.controller;
import com.example.hello_common.model.query.LocalDateQuery;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.Date;
@RestController
@RequestMapping("/date")
public class DateController {
@GetMapping("/localDate")
public String getDate(@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate) {
return "根据日期(LocalDate)查询数据。查询参数:" + localDate;
}
@GetMapping("/localDateQuery")
public String getDateQuery(LocalDateQuery localDateQuery) {
return "根据日期Query(LocalDateQuery)查询数据。查询参数:" + localDateQuery;
}
@GetMapping("/date")
public String getDate(@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date) {
return "根据日期(Date)查询数据。查询参数:" + date;
}
}
三、接口调用效果
远程接口
FeignClient调用远程接口效果
@RequestParam 直接传递请求参数
FeignClient接口调用日志:
@SpringQueryMap传递请求参数对象
FeignClient接口调用日志:
四、Date与@DateTimeFormat
@RequestParam + @DateTimeFormat + Date,有效
FeignClient 和 调用FeignClient 的代码,在上面的代码中已经给出。
调用效果:
FeignClient日志:
@SpringQueryMap + @DateTimeFormat + Date,无效
注意,在 @SpringQueryMap
修饰的参数对象中,如果使用了 java.util.Date
类型的字段,此时 @DateTimeFormat
是无效的。
比如下面代码中的 endDate
package com.example.hello_common.model.query;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.Date;
@Data
public class LocalDateQuery {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate beginDate;
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private Date endDate;
}
报错如下:
五、@DateTimeFormat在Feign低版本无效
经过测试,在 SpringBoot1.5 中,@RequestParam + @DateTimeFormat + Date
是无效的。
请参考:
https://blog.csdn.net/hysxchina/article/details/102907861