【问题标题】:"Ambiguous mapping found" when one @Controller extends another @Controller当一个@Controller 扩展另一个@Controller 时,“发现不明确的映射”
【发布时间】:2015-07-22 18:35:50
【问题描述】:

我有一个ImportAction 类,它作为几个特定类型导入控制器的父类,例如ImportClientsActionImportServicesAction

ImportAction 是一个带有 @Controller 注释的 Spring MVC 类,并具有 @RequestMapping-annotated 方法来拉出导入选项菜单并输入每个特定于类型的导入控制器。

每个子类,例如ImportClientsAction 也被注解为 @Controller 并且具有特定类型的 @RequestMappings 用于其类型的特定导入过程。

任何子类中的@RequestMappings 都不应与父类或彼此发生冲突;每个都有不同的路径/值和不同的参数。

根据我在this onethis one 等问题中遇到的情况,听起来Spring 将每个子类都视为具有父类的@RequestMapping 注释方法的副本,即使子类确实如此不覆盖父级的方法。

有没有办法让@Controller-annotated 父类与@RequestMappings,并拥有@Controller-annotated 子类,而 Spring 不会将子类视为重复父类的 @RequestMapping-annotated 方法?

额外的问题,为什么 Spring 不能识别子类上的 @RequestMapping“重复”,而忽略除父版本之外的所有版本?这是否根本没有实现,或者 Java 中是否存在使这不可能实现的基本问题?


编辑:示例代码

父类示例:

@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 */

}

子类示例:

@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 */

}

【问题讨论】:

  • 您能发布一个完整且可重现的示例吗?
  • 如果你覆盖了父母的方法;否则,它是模棱两可的。
  • @SotiriosDelimanolis 完成。
  • 是的,您将不得不以某种方式拆分处理程序方法。因为超类是具体的(而不是抽象的)并且使用@Controller 注释,所以Spring 将为它创建一个实例并注册它的方法。它会为继承了这些方法的子类做同样的事情。
  • 当您有两个子类并且每个子类都提供一个@Controller bean 时,问题变得更加明显。它们都从超类继承了一个处理程序方法。 Spring MVC 使用哪个实例作为方法调用的目标?

标签: java spring-mvc inheritance controller


【解决方案1】:

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

一个@Controller-annotated 类不应扩展另一个@Controller-annotated 类,因为父类的方法也存在于子类中。

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

当您有两个@Controller-annotated 类,一个是另一个的子类时,子类会尝试第二次在父类上注册映射。 “没什么大不了!”你说。问题是 Spring 无法明确决定使用哪个 instance 来调用映射方法,即使它是完全相同的方法。

如果您注册两个相同类型/类的 bean,同样的问题也适用,两者都尝试注册相同的映射。

Spring 使用错误的实例有几种方式会出现问题:

  1. 子代覆盖父代的方法。它甚至不必重写映射方法,只需从映射方法调用的方法。子实例的行为与父实例的行为不同,因此它们不能具有相同的映射。
  2. 该类具有非静态字段。即使两个 bean 是同一个类,这也适用。由于实例字段的值,一个实例/bean 可以具有不同的值,从而具有不同的行为。

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

related question 中,我尝试通过创建@RequestMapping 注释方法static 来解决这个问题。问题 1 仍然适用,因此简单地使每个映射方法 static 并不能解决或解决问题。

【讨论】:

    猜你喜欢
    • 2016-07-19
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多