没有类型参数的继承控制器方法不会与 RequestMapping 映射
Inherited controller method without type parameter does not get mapped with RequestMapping
我为我最新的 Web 应用程序项目创建了一个基础 Spring 控制器,我从它继承了我所有的基本 CRUD 控制器,称为 CrudController:
class CrudController<T, K extends Serializable>
T 是实体类型,K 是用于该类型的键(几乎是 Spring 的 CrudRepository 所需的参数)。我通过扩展它来创建一个休息控制器,如下所示:
@RestController
@RequestMapping(path = "/hats")
public class HatController extends CrudController<Hat, Integer> {
}
一切正常,除了获取项目列表的方法 /hats
。使用这种方法,我得到一个 405 Method Not Allowed。当我查看启动期间完成的日志记录时,我可以看到 RequestMappingHandlerMapping 没有映射 {[/hats],methods=[GET]}
但它确实映射了控制器中的其他四个方法。这是未映射的方法的代码:
@RequestMapping(method = RequestMethod.GET)
public HttpEntity<?> getAll() {
Iterable<T> result = controllerRepository.findAll();
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
经过多次试验,我发现如果我向 getAll 方法添加一个参数,该参数是 class 参数类型之一,该方法将被映射。检查这个非常相似的代码:
@RequestMapping(method = RequestMethod.GET)
public HttpEntity<?> getAll(K dontuse) {
Iterable<T> result = controllerRepository.findAll();
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
通过那个小的代码更改,/find
调用可以正常工作。我可以把我的虚拟参数放在那里,一切都会正常工作,但它有味道。
有什么想法吗?可以在此处找到复制该问题的简化项目:
目前 Java 中存在一个错误,请参阅错误报告 here and here, where Class#getDeclaredMethods()
returns 一个桥 Method
用于声明为 superclass 的每个继承方法包私有。根据 javadoc,它不应该那样做。
这混淆了 Spring MVC 对 @Controller
注释 classes 和处理程序方法的检查。在此答案中详细介绍不会很有用,但您可以查看处理它的代码 here.
最简单的解决方案是将您的 CrudRepository
class 声明为 public
。
public class CrudController<T, K extends Serializable>
我为我最新的 Web 应用程序项目创建了一个基础 Spring 控制器,我从它继承了我所有的基本 CRUD 控制器,称为 CrudController:
class CrudController<T, K extends Serializable>
T 是实体类型,K 是用于该类型的键(几乎是 Spring 的 CrudRepository 所需的参数)。我通过扩展它来创建一个休息控制器,如下所示:
@RestController
@RequestMapping(path = "/hats")
public class HatController extends CrudController<Hat, Integer> {
}
一切正常,除了获取项目列表的方法 /hats
。使用这种方法,我得到一个 405 Method Not Allowed。当我查看启动期间完成的日志记录时,我可以看到 RequestMappingHandlerMapping 没有映射 {[/hats],methods=[GET]}
但它确实映射了控制器中的其他四个方法。这是未映射的方法的代码:
@RequestMapping(method = RequestMethod.GET)
public HttpEntity<?> getAll() {
Iterable<T> result = controllerRepository.findAll();
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
经过多次试验,我发现如果我向 getAll 方法添加一个参数,该参数是 class 参数类型之一,该方法将被映射。检查这个非常相似的代码:
@RequestMapping(method = RequestMethod.GET)
public HttpEntity<?> getAll(K dontuse) {
Iterable<T> result = controllerRepository.findAll();
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
通过那个小的代码更改,/find
调用可以正常工作。我可以把我的虚拟参数放在那里,一切都会正常工作,但它有味道。
有什么想法吗?可以在此处找到复制该问题的简化项目:
目前 Java 中存在一个错误,请参阅错误报告 here and here, where Class#getDeclaredMethods()
returns 一个桥 Method
用于声明为 superclass 的每个继承方法包私有。根据 javadoc,它不应该那样做。
这混淆了 Spring MVC 对 @Controller
注释 classes 和处理程序方法的检查。在此答案中详细介绍不会很有用,但您可以查看处理它的代码 here.
最简单的解决方案是将您的 CrudRepository
class 声明为 public
。
public class CrudController<T, K extends Serializable>