2015-12-21 78 views
6

我在我的Spring應用程序REST端點,看起來像這樣ZonedDateTime如PathVariable在彈簧安置RequestMapping

@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?

或者是作爲String傳遞的唯一方法,然後自己進行轉換?如果是的話,是否有一種通用的方法來處理類似設計的多種方法?

+0

'ZonedDateTime'是相對較新的,並且Spring可能尚未更新以直接支持它。請參閱JasonZ的回答,尋找解決方法。 – Powerlord

回答

6

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時間戳進行上述任何操作。 The canonical way做時間戳到ZonedDateTime轉換是通過Instant#ofEpochSecond(long),給定一個合適的ZoneId

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對象。


在春季啓動,我想你可以申報相應Converter一個@Bean,它會自動註冊它,但不要把我的話。

5

你需要接受你傳遞給@PathVariable的數據類型爲String,然後自己進行轉換,你的錯誤日誌很清楚地告訴你。

不幸的是,彈簧庫無法通過@PathVariable綁定字符串值「1446361200」到ZonedDateTime類型。

+0

你說的是對的,但這是關於Spring的轉換,而不是Jackson。 – chrylis

1

默認情況下,@PathVariable僅支持有限的一組類型包括7種基本類型(booleanbyteshortintlongfloat,和double)加Date

但是,在控制器中使用an @InitBinderextend that是可能的,並添加了對ZonedDateTime.class的綁定。我不確定你是否可以在外部類中定義這個,但是如果不是,你需要在每個使用ZonedDateTime的控制器中定義這個@InitBinder

編輯:您可能需要創建自定義PropertyEditor並使用registerCustomEditor將其綁定來執行此操作。