我的Spring应用程序中有一个REST端点,如下所示
@RequestMapping(value="/customer/device/startDate/{startDate}/endDate/{endDate}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
public Page<DeviceInfo> getDeviceListForCustomerBetweenDates(@PathVariable ZonedDateTime startDate, @PathVariable ZonedDateTime endDate, Pageable pageable) {
... code here ...
}
我尝试将路径变量传递为毫秒和秒。但是,我从两个方面得到以下异常:
"Failed to convert value of type 'java.lang.String' to required type 'java.time.ZonedDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.web.bind.annotation.PathVariable java.time.ZonedDateTime for value '1446361200'; nested exception is java.time.format.DateTimeParseException: Text '1446361200' could not be parsed at index 10"
有人可以解释我如何传入(如秒或毫秒)字符串(例如1446361200)并将其转换为ZonedDateTime吗?
或者是唯一的传递方式,然后自己进行转换?如果是这样,有一种通用的方法来处理具有类似设计的多种方法吗?
答案 0 :(得分:11)
ZonedDateTime
参数有一个默认转换器。它使用Java 8 DateTimeFormatter
创建的
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
就你而言,这可能是任何FormatStyle
或任何DateTimeFormatter
,你的例子是行不通的。 DateTimeFormatter
解析和格式化日期字符串,而不是时间戳,这是您提供的。
您可以为参数提供适当的自定义@org.springframework.format.annotation.DateTimeFormat
,例如
public Page<DeviceInfo> getDeviceListForCustomerBetweenDates(
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime startDate,
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endDate,
Pageable pageable) { ...
或使用适当的pattern
和相应的日期字符串,例如
2000-10-31T01:30:00.000-05:00
您将无法使用unix时间戳执行上述任何操作。在适当ZonedDateTime
的情况下,The canonical way要ZoneId
转化的时间戳是Instant#ofEpochSecond(long)
。
long startTime = 1446361200L;
ZonedDateTime start = Instant.ofEpochSecond(startTime).atZone(ZoneId.systemDefault());
System.out.println(start);
要使其与@PathVariable
一起使用,请注册自定义Converter
。像
class ZonedDateTimeConverter implements Converter<String, ZonedDateTime> {
private final ZoneId zoneId;
public ZonedDateTimeConverter(ZoneId zoneId) {
this.zoneId = zoneId;
}
@Override
public ZonedDateTime convert(String source) {
long startTime = Long.parseLong(source);
return Instant.ofEpochSecond(startTime).atZone(zoneId);
}
}
并在WebMvcConfigurationSupport
@Configuration
注释类中注册,覆盖addFormatters
@Override
protected void addFormatters(FormatterRegistry registry) {
registry.addConverter(new ZonedDateTimeConverter(ZoneId.systemDefault()));
}
现在,Spring MVC将使用此转换器将String
路径段反序列化为ZonedDateTime
对象。
在Spring Boot中,我认为你可以为相应的@Bean
声明一个Converter
,它会自动注册,但不要相信我的话。
答案 1 :(得分:5)
您需要接受作为@PathVariable
数据类型传递给String
的内容,然后自行进行转换,您的错误日志会清楚地告诉您。
不幸的是,Spring库无法通过ZonedDateTime
绑定将字符串值“1446361200”转换为@PathVariable
类型。
答案 2 :(得分:1)
默认情况下,@PathVariable
仅支持一组有限的类型,包括7种基本类型(boolean
,byte
,short
,int
,{{ 1}},long
和float
)加double
。
但是,您可以extend that在控制器中使用an @InitBinder
并为Date
添加绑定。我不确定你是否可以在外部类中定义它,但是......如果不是,你需要在每个使用ZonedDateTime.class
的控制器中定义这个@InitBinder
。
修改:您可能需要创建自定义PropertyEditor
并使用ZonedDateTime
对其进行绑定才能执行此操作。