2017-05-18 93 views
2

我有WebDeviceInfoIOSDeviceInfo類是DeviceInfo的子類。如何在彈簧@RestController中創建單個端點,以接受IOSDeviceInfoWebDeviceInfo接受兩個不同的子類具有相同的@RequestMapping

嘗試#1

我試圖映射相同RequestMapping以兩種不同的方法,如果RequestBody可以映射到一個WebDeviceInfo和其他將被調用,一個會被調用,如果RequestBody能被映射到IOSDeviceInfo

@RequestMapping(value = "/register-device", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) 
public void registerWebDevice(@RequestBody final WebDeviceInfo webDeviceInfo) { 
    //register web device 
} 

@RequestMapping(value = "/register-device", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) 
public void registerIOSDevice(@RequestBody final IOSDeviceInfo iosDeviceInfo) { 
    //register ios device 
} 

但是,這並不工作,第二RequestMapping沒有得到註冊和應用程序無法啓動,因爲春天是看到與/register-device相同RequestMethodMediaType已被映射到另一種方法。

嘗試#2

接着,我試圖接受超類作爲RequestBody,然後將其澆注到適當的子類。

@RequestMapping(value = "/register-device", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) 
public void registerDevice(@RequestBody final DeviceInfo deviceInfo) { 
    if (deviceInfo instanceof WebDeviceInfo) { 
     final WebDeviceInfo webDeviceInfo = (WebDeviceInfo) deviceInfo; 
     //register web device 
    } else if (deviceInfo instanceof IOSDeviceInfo) { 
     final IOSDeviceInfo iosDeviceInfo = (IOSDeviceInfo) deviceInfo; 
     //register ios device 
    } else { 
     logger.debug("Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo"); 
    } 
} 

這也行不通。我總是得到:

Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo

嘗試3

最後,我試着只是投放到正確的子類try/catch內。

@RequestMapping(value = "/register-device", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) 
public void registerDevice(@RequestBody final DeviceInfo deviceInfo) { 
    try { 
     final WebDeviceInfo webDeviceInfo = (WebDeviceInfo) deviceInfo); 
     //register web device 
    } catch (final ClassCastException ex) { 
     try { 
      final IOSDeviceInfo iosDeviceInfo = (IOSDeviceInfo) deviceInfo); 
      //register ios device 
     } catch (final ClassCastException ex2) { 
      logger.debug("Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo"); 
     } 
    } 
} 

我再次得到錯誤:

Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo

有沒有辦法做到這一點,還是我將不得不創建兩個單獨的方法有兩種不同的RequestMapping S'

+0

它不以這種方式工作,你需要你的httpMssagerConverter延伸到'deserialize' http請求,這應該很容易,如果你使用'jackson' – Jaiwo99

+0

對於第二次和第三次嘗試,Spring MVC應該如何決定將內容反序列化爲「IOSDeviceInfo」還是「WebDeviceInfo」? –

+0

@ Jaiwo99你有沒有關於如何重寫Spring提供的默認示例的示例? –

回答

0

您可以使用@PathVariable的參數來定義哪種類型,你需要反序列化

public void registerDevice(@PathVariable("deviceType") String deviceType, @RequestBody final DeviceInfo deviceInfo) { 

switch (deviceType){ 
... 
} 
0

您可以使用相同的@RequestMapping,但是,你仍然需要一些東西來區分它們。同樣,我的意思是相同的名稱,路徑和RequestMethod。

您可以在請求映射中使用params參數來區分它們。

例如,

@RequestMapping(value = "/register-device", 
    method = RequestMethod.POST, 
    consumes = MediaType.APPLICATION_JSON_VALUE, 
    params="device=android") 
public void registerDevice(@RequestBody final WebDeviceInfo deviceInfo){ 

} 


@RequestMapping(value = "/register-device", 
    method = RequestMethod.POST, 
    consumes = MediaType.APPLICATION_JSON_VALUE,  
    params="device=ios") 
public void registerDevice(@RequestBody final IOSDeviceInfo deviceInfo){ 

} 

然後,只需添加一個額外的參數與關鍵「設備」的要求,而Spring會解決的正確方法。

例如,如果這是你原來的有效載荷:

{ 
    deviceInfo : {..} 
} 

它現在是這樣的:

{ 
    device : "ios", 
    deviceInfo : {..} 
} 
+0

不幸的是,這不適用於JSON有效內容中的值。這裏的'device'必須是一個請求參數,而不是POST JSON中的值。這需要將URL切換到'/ register-device?device = ios'或'/ register-device?device = web'。 –

相關問題