“发现不明确的映射"当一个@Controller 扩展另一个@Controller [英] "Ambiguous mapping found" when one @Controller extends another @Controller

查看:54
本文介绍了“发现不明确的映射"当一个@Controller 扩展另一个@Controller的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a ImportAction class which serves as a parent class for several type-specific import controllers, such as ImportClientsAction and ImportServicesAction.

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

ImportAction is a Spring MVC annotated @Controller class and has @RequestMapping-annotated methods to pull up a menu of import options and enter each of the type-specific import controllers.

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

Each child class, e.g. ImportClientsAction is also annotated @Controller and has type-specific @RequestMappings for their type's specific import process.

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

None of the @RequestMappings in any of the child classes should ever collide with the parent or with each other; each has a different path/value and different params.

根据我在这个问题中遇到的问题这个,听起来 Spring 认为每个子类都具有父类的 @RequestMapping 注释方法的副本,即使子类没有覆盖父类的方法.

From what I've come across in questions like this one and this one, it sounds like Spring counts each child class as having a duplicate of the parent class's @RequestMapping-annotated methods, even if the child class does not override the parent's methods.

有没有办法让 @Controller 带有 @RequestMapping 注释的父类和 @Controller 注释子类,没有 Spring 将子类视为复制父类的 @RequestMapping 注释方法?

Is there a way to have an @Controller-annotated parent class with @RequestMappings, and have @Controller-annotated child classes, without Spring seeing the child classes as duplicating the parent's @RequestMapping-annotated methods?

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

Bonus question, why can't Spring recognize a @RequestMapping "duplicate" on a child class and just ignore all but the parent's version? Has this simply not been implemented, or is there a fundamental problem in Java that makes this impossible?

示例代码

父类示例:

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

}

推荐答案

(帽子提示 Sotirios Delimanolis 用于帮助我学习和理解这一点)

(Hat tip to Sotirios Delimanolis for helping me learn & understand this)

一个带有 @Controller 注释的类不应扩展另一个带有 @Controller 注释的类,因为父类的方法也存在于子类中.

One @Controller-annotated class should not extend another @Controller-annotated class, because the parent class's methods also exist on the child class.

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

Each @Controller-annotated class is instantiated as a bean in the servlet context (?), and that instance of the class (ie that bean) is then used to call @RequestMapping-annotated methods according to the mapping provided when a user makes a request to the servlet.

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

When you have two @Controller-annotated classes, one a child of the other, the child class tries to register the mappings on the parent a second time. "No big deal!" you say. The problem is that Spring has no way to definitively decide which instance to use to call the mapped method, even if it is exactly the same method.

如果你注册两个相同类型/类的 bean,同样的问题也适用,它们都试图注册相同的映射.

The same problem applies if you register two beans of the same type/class, where both try to register identical mappings.

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

There's a couple ways that Spring using the wrong instance would be problematic:

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

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

Because of these problems (and probably several others), Spring cannot ignore or work around duplicate mappings, even if the method that's mapped to is the same method.

在一个相关问题中,我尝试解决这是通过使 @RequestMapping 注释的方法 static 来实现的.问题 1 仍然适用,因此简单地使每个映射方法 static 并不能解决或解决问题.

In a related question, I tried working around this by making the @RequestMapping-annotated methods static. Problem 1 still applies, so simply making each mapped method static doesn't fix or work around the problem.

这篇关于“发现不明确的映射"当一个@Controller 扩展另一个@Controller的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆