Grails 5继承RestfulController时出现默认构造函数缺失问题
问题
正在将应用从Grails 2.5.2迁移至Grails 5.2.5,原Grails 2中有一个RestVehicleTrackingController继承自RestfulController,该控制器无需指定关联Domain,直接返回Map对象的JSON格式响应。但在Grails 5中,继承RestfulController时必须指定Domain,而我需要保留原有逻辑:查询任意Domain生成Map后返回JSON响应,尝试的代码如下:
URL映射
"/api/vehicleList/$gatepassNo?(.$format)?"(controller: 'restVehicleTracking', action: 'getVehicleList')
控制器代码
class RestVehicleTrackingController extends RestfulController { static allowedMethods = [search: 'GET', getVehicleList: 'GET'] def restCommonService def vehicleTrackingService def getVehicleList(String gatepassNo) { def ipAddress = restCommonService.getClientIpAddress(request) def url = '/api/ws/vt/gatePass/vehicleList' String requestParams = params.toString() if (gatepassNo) { def retVal = vehicleTrackingService.getVehicleInformation(gatepassNo) if (retVal) { restCommonService.storeRequestInformation(url, requestParams, retVal.toString(), true, ipAddress, 'DOWN',) respond retVal, formats: ['json', 'xml'] } } restCommonService.storeRequestInformation(url, requestParams, null, false, ipAddress, 'DOWN',) respond null, status: 404 } }
在Grails 2.5.2中代码运行正常,但在Grails 5.2.5中出现错误:
There is no default constructor available in class 'grails.rest.RestfulController'
解决方案
方案1:直接继承基础Controller类(推荐)
既然你的控制器不需要绑定特定Domain,也不需要RestfulController提供的默认CRUD方法,直接继承Grails基础的Controller类即可,完全保留原有业务逻辑:
class RestVehicleTrackingController extends Controller { static allowedMethods = [search: 'GET', getVehicleList: 'GET'] def restCommonService def vehicleTrackingService def getVehicleList(String gatepassNo) { def ipAddress = restCommonService.getClientIpAddress(request) def url = '/api/ws/vt/gatePass/vehicleList' String requestParams = params.toString() if (gatepassNo) { def retVal = vehicleTrackingService.getVehicleInformation(gatepassNo) if (retVal) { restCommonService.storeRequestInformation(url, requestParams, retVal.toString(), true, ipAddress, 'DOWN') respond retVal, formats: ['json', 'xml'] return // 提前返回,避免执行后续404逻辑 } } restCommonService.storeRequestInformation(url, requestParams, null, false, ipAddress, 'DOWN') respond null, status: 404 } }
注:添加return是为了和原Grails 2行为保持一致,确保找到数据后不会触发后续的404响应。
方案2:显式指定泛型并提供构造函数(仅当需要RestfulController功能时使用)
如果一定要继承RestfulController,需要显式指定泛型类型并提供构造函数。由于不需要绑定特定Domain,可以用Object作为泛型参数:
class RestVehicleTrackingController extends RestfulController<Object> { // 提供符合RestfulController要求的构造函数 RestVehicleTrackingController() { super(Object) } static allowedMethods = [search: 'GET', getVehicleList: 'GET'] def restCommonService def vehicleTrackingService def getVehicleList(String gatepassNo) { // 原有业务逻辑不变 def ipAddress = restCommonService.getClientIpAddress(request) def url = '/api/ws/vt/gatePass/vehicleList' String requestParams = params.toString() if (gatepassNo) { def retVal = vehicleTrackingService.getVehicleInformation(gatepassNo) if (retVal) { restCommonService.storeRequestInformation(url, requestParams, retVal.toString(), true, ipAddress, 'DOWN') respond retVal, formats: ['json', 'xml'] return } } restCommonService.storeRequestInformation(url, requestParams, null, false, ipAddress, 'DOWN') respond null, status: 404 } }
注:此方案会引入RestfulController的默认CRUD方法(如index、show等),如果不需要这些方法,需要额外配置禁用,因此优先推荐方案1。
内容的提问来源于stack exchange,提问作者Sumon Bappi
相关产品推荐
相关产品推荐

