"Ambiguous mapping found" 当一个@Controller 扩展另一个@Controller

"Ambiguous mapping found" when one @Controller extends another @Controller

我有一个 ImportAction class 作为 parent class 用于几个 type-specific 导入控制器,例如 ImportClientsActionImportServicesAction.

ImportAction 是一个 Spring MVC 注释 @Controller class 并且有 @RequestMapping 注释的方法来拉出导入选项的菜单并输入每个选项type-specific 个导入控制器。

每个 child class,例如ImportClientsAction 也被注释为 @Controller 并且具有 type-specific @RequestMapping 用于其类型的特定导入过程。

None 的 @RequestMapping 在任何 child class 中都应该与 parent 或彼此发生碰撞;每个都有不同的 path/value 和不同的参数。

根据我在 and this one 等问题中遇到的情况,听起来 Spring 将每个 child class 视为具有 [=77] 的副本=] class 的 @RequestMapping 注释方法,即使 child class 没有覆盖 parent 的方法。

有没有办法让 @Controller-注解 parent class 和 @RequestMappings,并有 @Controller-注解 child classes,没有 Spring 将 child classes 视为复制 parent 的 @RequestMapping-注释方法?

额外的问题,为什么 Spring 无法识别 child class 上的 @RequestMapping "duplicate" 而只忽略 [=77 以外的所有内容=]的版本?这是根本没有实现,还是 Java 中存在根本性问题导致无法实现?


编辑:示例代码

Parent class 示例:

@Controller
public class ImportAction {

    @RequestMapping(value = "/import", params = "m=importMenu", method = RequestMethod.GET)
    public String importMenu(HttpServletRequest request) throws Exception {
        return TilesConstants.IMPORT_MENU;
    }

    @RequestMapping(value = "/import", params = "m=importClients", method = RequestMethod.GET)
    public String importClients(@ModelAttribute("ImportUploadForm") ImportUploadForm theForm, HttpServletRequest request) throws Exception {
        retrieveReturnPage(request);
        theForm.setSomeBoolean(true);
        return TilesConstants.IMPORT_CLIENTS_UPLOAD;
    }

    @RequestMapping(value = "/import", params = "m=importServices", method = RequestMethod.GET)
    public String importServices(@ModelAttribute("ImportUploadForm") ImportUploadForm theForm, HttpServletRequest request) throws Exception {
        retrieveReturnPage(request);
        theForm.setSomeBoolean(false);
        return TilesConstants.IMPORT_SERVICES_UPLOAD;
    }

    /* etc 7 more almost identical methods */

}

Child class 示例:

@Controller
public class ImportClientsAction extends ImportAction {

    @RequestMapping(value = "/importClients", params = "m=uploadClients", method = RequestMethod.POST)
    public String uploadClients(@ModelAttribute("ImportUploadForm") ImportUploadForm theForm, BindingResult errors, HttpServletRequest request) throws Exception {
        if (!parseAndStoreUploadedFile(theForm, errors, request)) {
            return TilesConstants.IMPORT_CLIENTS_UPLOAD;
        }

        return "redirect:/importClients?m=enterMapClientsUpload";
    }

    /* etc other "client" type-specific import methods */

}

(感谢 Sotirios Delimanolis 帮助我学习和理解这一点)

一个 @Controller-注释的 class 不应扩展另一个 @Controller-注释的 class,因为 parent class 的方法也存在于 child class.

每个 @Controller-注释的 class 在 servlet 上下文中被实例化为一个 bean(?),然后 class 的实例(即那个 bean)用于当用户向 servlet 发出请求时,根据提供的映射调用 @RequestMapping-注解方法。

当您有两个 @Controller-注释的 class 时,一个是另一个的 child,child class 会尝试注册映射第二次在 parent 上。 "No big deal!"你说。问题是 Spring 无法明确决定使用哪个 实例 来调用映射的方法,即使它是完全相同的方法。

如果您注册两个相同 type/class 的 bean,也会出现同样的问题,这两个 bean 都尝试注册相同的映射。

有几种方法 Spring 使用错误的实例会产生问题:

  1. child 覆盖了parent 的方法。它甚至不必覆盖映射的方法,只需从映射的方法中调用一个方法即可。 child 实例的行为与 parent 实例的行为不同,因此它们不能具有相同的映射。
  2. class 有 non-static 个字段。即使两个 bean 相同 class,这也适用。一个 instance/bean 可以有不同的值,因此由于实例字段的值而导致不同的行为。

由于这些问题(可能还有其他几个问题),Spring 无法忽略或解决重复映射,即使映射到的方法是相同的方法。

related question 中,我尝试通过制作 @RequestMapping-注释方法 static 来解决这个问题。问题 1 仍然存在,因此简单地制作每个映射方法 static 并不能解决或解决问题。