当一个@Controller扩展另一个@Controller时,“模糊映射”

时间:2015-07-22 18:35:50

标签: java spring-mvc inheritance controller

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

ImportAction是一个Spring MVC注释@Controller类,并且有@RequestMapping个带注释的方法,用于提取导入选项菜单并输入每个特定于类型的导入控制器。

每个儿童班,例如ImportClientsAction也带有注释@Controller,并且针对其类型的特定导入过程具有特定于类型的@RequestMapping

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

从我在this onethis one等问题中遇到的情况来看,听起来像Spring将每个子类视为父类的@RequestMapping - 带注释方法的副本,即使子类没有覆盖父类的方法。

有没有办法让@Controller - 带有@RequestMapping的带注释的父类,并且有@Controller个带注释的子类,没有Spring看到子类重复了父类{ {1}} - 带注释的方法?

奖金问题,为什么Spring不能在子类上识别@RequestMapping“重复”并忽略除父级版本之外的所有内容?这有没有被实现,或者Java中存在一个根本问题,这使得这不可能吗?

编辑:示例代码

父类示例:

@RequestMapping

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

}

1 个答案:

答案 0 :(得分:4)

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

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

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

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

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

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

  1. 孩子会覆盖父母的方法。它甚至不必覆盖映射的方法,只是从映射方法调用的方法。子实例的行为与父实例的行为不同,因此它们不能具有相同的映射。
  2. 该类具有非静态字段。即使两个bean是同一个类,这也适用。由于实例字段的值,一个实例/ bean可以具有不同的值,因此具有不同的行为。
  3. 由于这些问题(可能还有其他几个问题),Spring不能忽略或解决重复映射问题,即使映射到的方法是相同的方法。

    related question中,我尝试通过制作@RequestMapping - 带注释的方法static来解决此问题。问题1仍然适用,因此只需使每个映射方法static无法修复或解决问题。