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

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

问题描述

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



ImportAction 注释 @Controller 类并具有 @RequestMapping - 注释方法来提取导入选项菜单,并输入每个类型特定的导入控制器。



每个子类,例如 ImportClientsAction 也注释为 @Controller ,并且具有类型特定 @RequestMapping

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



根据我遇到的问题,如这一个 @RequestMapping的副本



有一种方法可以让 - 注释方法,即使子类不会覆盖父类的方法。 > @Controller - 注释了 @RequestMapping 的父类,并且具有 @Controller 注释子类,没有Spring看到子类重复父类的 @RequestMapping - 注释方法?



,为什么Spring不能在子类上识别一个 @RequestMapping duplicate,只是忽略除了父类的所有版本?这个简单没有实现,或者在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几乎相同的方法* /

}

子类示例:

  @Controller 
public class ImportClientsAction extends ImportAction {

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

returnredirect:/ importClients?m = enterMapClientsUpload;
}

/ * etc其他客户类型特定的导入方法* /

}


解决方案

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



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



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



@Controller - 注释类,一个是另一个的子对象,子类尝试第二次注册父对象的映射。 没什么大不了!你说。问题是,Spring没有办法明确决定哪个实例用于调用映射方法,即使它是完全相同的方法。



如果你注册两个相同类型/类的bean,这两个bean都尝试注册相同的映射。同样的问题也适用于Spring使用错误实例会有问题:


  1. 子项覆盖父项的方法。它甚至不必重写映射方法,只是从映射方法调用的方法。子实例的行为将与父实例的行为不同,因此它们不能具有相同的映射。

  2. 类具有非静态字段。即使两个bean是相同的类,这也适用。

由于这些问题(以及



在一个相关问题,我尝试通过使 @RequestMapping -annotated方法 static 。问题1仍然适用,因此只需使每个映射方法 static 不解决或解决问题。


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

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.

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

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.

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.

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?

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?


EDIT: Example code

Parent class example:

@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 example:

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

}

解决方案

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

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

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.

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.

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

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

  1. The child overrides the parent's methods. It doesn't even have to override the mapped methods, just a method called from a mapped method. The behavior for the child instance would be different than for the parent instance, so they can't have the same mapping.
  2. The class has non-static fields. This applies even if two beans are the same class. One instance/bean can have different values and thus different behavior due to the values of the instance fields.

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.

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天全站免登陆