使用相同的@RequestMapping

时间:2017-05-18 15:44:20

标签: java spring spring-mvc inheritance request-mapping

我有WebDeviceInfoIOSDeviceInfo个类,它们是DeviceInfo的子类。如何在弹簧@RestController中创建一个接受IOSDeviceInfoWebDeviceInfo的单个端点?

尝试#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没有注册,应用程序无法启动,因为Spring看到/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");
    }
}

这也不起作用。我总是得到:

  

无法将deviceInfo强制转换为WebDeviceInfo或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");
        }
    }
}

我再次收到错误:

  

无法将deviceInfo强制转换为WebDeviceInfo或IOSDeviceInfo

有没有办法实现这一点,或者我将不得不用两个不同的RequestMapping创建两个单独的方法?

2 个答案:

答案 0 :(得分:0)

您可以使用@PathVariable参数来定义反序列化所需的类型

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

switch (deviceType){
...
}

答案 1 :(得分: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){

}

然后只需使用键“device”向请求添加一个额外的参数,Spring将解析正确的方法。

例如,如果这是你原来的有效载荷:

{
   deviceInfo : {..}
}

现在就是这样:

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