需求描述
现有类型BaseCollectModelDTO
、CommonCollectModelDTO
、PluginCollectModelDTO
、CustomCollectModelDTO
,其中后三者是BaseCollectModelDTO
的子类,于是我想直接将controller方法参数定义为BaseCollectModelDTO
类(当然使用了@RequestBody
注解),当需要传子类型的参数时,直接通过这个controller方法搞定,不需要再去写其他controller方法。
@RequestMapping(value = "/addModel")
protected Result<Boolean> addModel(@RequestBody BaseCollectModelDTO dto){
//调用门面方法,最终会调用到实际的子类
return Result.success(collectModelFacade.addModel(dto));
}
同时,addModel方法接收的是继承了BaseCollectModelDTO
类的泛型参数,各个子类参数类型为实际类型
比如PluginCollectModelServiceImpl
public void addModel(PluginCollectModelDTO pluginCollectModelDTO)
比如CommonCollectModelServiceImpl
public void addModel(CommonCollectModelDTO commonCollectModelDTO)
问题
问题1:当子类json参数通过前端传入controller时,发现转化后是BaseCollectModelDTO
类型,
问题2:当进入service时,由于传入的是BaseCollectModelDTO
,而方法参数类型为子类,就报了类型转化异常
解决
既然一个controller方法无法解析所有类型参数,那么需要写各自的controller传递不同的参数,但是这样又会导致重复代码。
于是使用泛型,定义在父类里
public class BaseCollectModelController<T extends BaseCollectModelDTO> {
@RequestMapping(value = "/addModel")
protected Result<Boolean> addModel(@RequestBody T dto){
return Result.success(collectModelFacade.addModel(dto));
}
}
不同子类实现该父类,并传实际泛型类型,也无需再写新controller方法
@RestController
@RequestMapping(value = "/commonCollectModel")
public class CommonCollectModelController extends BaseCollectModelController<CommonCollectModelDTO>{
}
引申
在springmvc中,有@RequestBody
注解的参数是什么类型,那么前端传到后台后就是什么类型,如果将父类型传给子类型就会报类型转化异常,这是springmvc自身机制所致的。
但是对于@ResponseBody
,只要返回值类型是其子类或者类本身都可以。
比如下面的方法,方法返回值为BaseCollectModelVO
,那么返回BaseCollectModelVO
或者子类CommonCollectModelVO
都可以,mvc会按照实际类型数据结构来渲染。
@ResponseBody
public BaseCollectModelVO detailModel(BaseCollectModelDTO dto){
return collectModelFacade.detailModel(dto);
}