2017-05-18 1 views
2

Ich habe WebDeviceInfo und IOSDeviceInfo Klassen, die Unterklassen von DeviceInfo sind. Wie kann ich einen einzelnen Endpunkt in einer Quelle erstellen, die entweder IOSDeviceInfo oder WebDeviceInfo akzeptiert?Akzeptieren Sie zwei verschiedene Unterklassen mit demselben @RequestMapping

Versuch # 1

Ich habe versucht, die gleichen RequestMapping auf zwei verschiedene Methoden zur Karte, eine, die, wenn die RequestBody könnte zu einem WebDeviceInfo und das andere abgebildet werden erhalten genannt würde, die, wenn die RequestBody aufgerufen würde könnte auf eine IOSDeviceInfo gemappt werden.

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

Aber das funktioniert nicht, die zweiten RequestMapping nicht registrieren lassen und die Anwendung nicht starten, weil Frühling sieht, dass /register-device mit den gleichen RequestMethod und MediaType bereits einem anderen Verfahren abgebildet wird.

Versuch # 2

Als nächstes habe ich versucht, die übergeordnete Klasse als RequestBody zu akzeptieren und dann auf die entsprechende Unterklasse Gießen.

@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"); 
    } 
} 

Dies funktioniert auch nicht. Ich habe immer bekommen:

Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo

Versuch # 3

Schließlich habe ich versucht, Gießen nur auf die richtige Unterklasse innerhalb eines 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"); 
     } 
    } 
} 

Wieder erhalte ich Fehler:

Could not cast deviceInfo to WebDeviceInfo or IOSDeviceInfo

Gibt es eine Möglichkeit, dies zu erreichen, oder werde ich zwei verschiedene Methoden mit zwei verschiedenen RequestMapping s zu schaffen haben?

+0

es auf diese Weise nicht funktioniert, müssen Sie Ihre httpMssagerConverter zu 'deserialize' die HTTP-Anforderung zu erweitern, die sollte sehr einfach sein, wenn Sie 'jackson' verwenden – Jaiwo99

+0

Wie sollte Spring MVC entscheiden, den Inhalt für den zweiten und dritten Versuch entweder als' IOSDeviceInfo' oder als 'WebDeviceInfo' zu deserialisieren? –

+0

@ Jaiwo99 Haben Sie ein Beispiel dafür, wie Sie den Standard, den Spring bietet, außer Kraft setzen? –

Antwort

0

Sie können @PathVariable auf den Parameter verwenden, um festzulegen, welche Art Sie jedoch

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

switch (deviceType){ 
... 
} 
0

Sie können die gleiche @RequestMapping, verwenden deserialisieren benötigen, können Sie noch etwas brauchen, um sie zu unterscheiden. Mit demselben meine ich den gleichen Namen, Pfad und RequestMethod.

Sie können das Argument params im Anforderungsmapping verwenden, um sie zu unterscheiden.

Zum Beispiel

@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){ 

} 

Dann einfach einen zusätzlichen Parameter auf die Anforderung mit der Taste „Gerät“, hinzufügen und Frühling wird die richtige Methode lösen.

z.B.Wenn diese ursprüngliche Nutzlast sind:

{ 
    deviceInfo : {..} 
} 

es jetzt sein würde:

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

Leider funktioniert dies nicht für einen Wert in der JSON-Nutzlast. Das "Gerät" müsste hier ein Anfrage-Parameter sein und nicht ein Wert im POST-JSON. Dazu müsste die URL auf '/ register-device? Device = ios' oder'/register-device? Device = web' gesetzt werden. –

Verwandte Themen