这次我正在使用Declarative REST Client,在一些Spring Boot App中使用。
我想要实现的是调用我的一个REST API,如下所示:
@RequestMapping(value = "/customerslastvisit", method = RequestMethod.GET)
public ResponseEntity customersLastVisit(
@RequestParam(value = "from", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date from,
@RequestParam(value = "to", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date to) {
正如您所看到的,API接受带有from和to params的调用,格式为(yyyy-MM-dd)
为了调用该API,我已准备好以下@FeignClient
:
@FeignClient("MIIA-A")
public interface InboundACustomersClient {
@RequestMapping(method = RequestMethod.GET, value = "/customerslastvisit")
ResponseEntity customersLastVisit(
@RequestParam(value = "from", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date from,
@RequestParam(value = "to", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date to);
}
一般来说,几乎是复制粘贴。现在在我的启动应用程序的某个地方,我使用它:
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
ResponseEntity response = inboundACustomersClient.customersLastVisit(formatter.parse(formatter.format(from)),
formatter.parse(formatter.format(to)));
而且,我得到的是那个
嵌套异常是 org.springframework.core.convert.ConversionFailedException:失败 从类型[java.lang.String]转换为type [@ org.springframework.web.bind.annotation.RequestParam @ org.springframework.format.annotation.DateTimeFormat java.util.Date] for value' Sun May 03 00:00:00 CEST 2015';
嵌套异常是java.lang.IllegalArgumentException:无法 解析' Sun May 03 00:00:00 CEST 2015'
所以,问题是,我对请求做错了什么,它没有解析到"仅限日期"发送到我的API之前的格式?或者它可能是一个纯粹的Feign lib问题?
答案 0 :(得分:7)
您应该创建并注册假日格式化程序以自定义日期格式
@Component
public class DateFormatter implements Formatter<Date> {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
@Override
public Date parse(String text, Locale locale) throws ParseException {
return formatter.parse(text);
}
@Override
public String print(Date date, Locale locale) {
return formatter.format(date);
}
}
@Configuration
public class FeignFormatterRegister implements FeignFormatterRegistrar {
@Override
public void registerFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter());
}
}
答案 1 :(得分:1)
另一个简单的解决方案是使用默认接口方法进行日期到字符串转换,如
@RequestMapping(value = "/path", method = GET)
List<Entity> byDate(@RequestParam("date") String date);
default List<Entity> date(Date date) {
return date(new SimpleDateFormat("dd.MM.yyyy").format(validityDate));
}
答案 2 :(得分:0)
这是一种线程安全的解决方案,并且不会在您的Spring Universe中注册默认日期格式程序。但是请记住,此格式化程序将作为所有假冒客户端使用的新默认值,并且您实际上应使用joda日期时间或新的Java日期时间:
@Configuration
public class FeignFormatterRegister implements FeignFormatterRegistrar {
@Override
public void registerFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter());
}
/*
* SimpleDateFormat is not thread safe!
* consider using joda time or java8 time instead
*/
private static class DateFormatter implements Formatter<Date> {
static final ThreadLocal<SimpleDateFormat> FORMAT = ThreadLocal.withInitial(
() -> new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
);
@Override
public Date parse(String text, Locale locale) throws ParseException {
return FORMAT.get().parse(text);
}
@Override
public String print(Date date, Locale locale) {
return FORMAT.get().format(date);
}
}
}
答案 3 :(得分:0)
您可以只使用扩展器对象。
/**
* @see com.x.y.z.rest.configuration.SomeController#search(Integer, Integer, Date, Date)
*/
@RequestLine("GET /configuration/{customerId}?&startDate={startDate}")
Set<AnObject> searchSomething(@Param("customerId") Integer customerId, @Param(value = "startDate", expander = FeignDateExpander.class) Date startDate);
public class FeignDateExpander implements Param.Expander {
@Override
public String expand(Object value) {
Date date = (Date)value;
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
}
}
答案 4 :(得分:0)
假冒客户端(现在(2020年12月))可以使用上面原始问题中的语法并将java.time.LocalDate
作为参数来正常工作。也就是说,您可以使用:
@FeignClient(name = "YOUR-SERVICE")
interface ClientSpec {
@RequestMapping(value = "/api/something", method = RequestMethod.GET)
String doSomething(
@RequestParam("startDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate startDate);
}