繁体   English   中英

Spring RestController 中的继承

[英]Inheritance in Spring RestController

我有一个 Spring RestController 来处理 API 调用的第 1 版。

package rest.v1;

@RestController
@RequestMapping("v1/someResource")
public class Controller_V1 {

    @RequestMapping(value = "/{resourceName}", method = RequestMethod.GET)
    public Object retrieve() throws Exception {
        ....
    }
}

我想要做的是创建另一个处理版本 2 请求的控制器。 同时,我想继承版本 1 控制器中已经存在的实现。 这是因为从 v1 到 v2 没有改变的实现将像从 v1 一样继承。

所以像这样:

package rest.v2;

@RestController("controllerV2")
@RequestMapping("v2/someResource")
public class Controller_v2 extends Controller_v1 {

    @RequestMapping(value = "/{resourceName}", method = RequestMethod.GET)
    public Object retrieve() throws Exception {
        //implementation overridden from v1
    }
}

这样做会导致 ConflictingBeanDefinitionException。 我也不确定是否应该像上面那样扩展控制器。

我知道我可以在同一个控制器的 RequestMapping 中使用多个路径,如下所示:

@RestController
@RequestMapping(value = { "v1/someResource", "v1/someResource" })
public class Controller_V1 {

}

但以上内容不适用于我的场景。

这是扩展控制器时的堆栈跟踪:

 [java] org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [rest-context.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'controller_V1' for bean class [rest.v2.Controller_V2] conflicts with existing, non-compatible bean definition of same name and class [rest.v1.Controller_V1]
     [java]     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:413)
     [java]     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:335)
     [java]     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
     [java]     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
     [java]     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)
     [java]     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
     [java]     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
     [java]     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
     [java]     at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
     [java]     at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:540)
     [java]     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:454)
     [java]     at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
     [java]     at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:624)
     [java]     at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:672)
     [java]     at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:543)
     [java]     at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
     [java]     at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
     [java]     at javax.servlet.GenericServlet.init(GenericServlet.java:158)

问题在堆栈跟踪的第一行中很明显:

org.springframework.beans.factory.BeanDefinitionStoreException:从类路径资源 [rest-context.xml] 解析 XML 文档时出现意外异常; 嵌套异常是org.springframework.context.annotation.ConflictingBeanDefinitionException :bean 类 [rest.v2.Controller_V2] 的注释指定的bean 名称 'controller_V1'与相同名称和类 [rest.v1.控制器_V1]

这是因为您让 Spring 为您的 bean 命名。 默认情况下,Spring 将使用驼峰命名法中当前类的接口或超类的名称作为 bean 名称。

所以,你有这样的东西(Spring 给出的名字):

@RestController("controller_V1") //<-- that's the name of the Spring bean
@RequestMapping("v1/someResource")
public class Controller_V1

@RestController("controller_V1") //<-- that's the name of the Spring bean
@RequestMapping("v2/someResource")
public class Controller_V2 extends Controller_V1

如您所见,您只需要重命名您的第二个 bean:

@RestController("controller_V2")
@RequestMapping("v2/someResource")
public class Controller_V2 extends Controller_V1

IMO 你应该为你的课程使用更好的名字。

@RestController 扩展目前可用。 由于新的方法实现版本,我需要扩展 @RestController。 我试图扩展一个@RestController,它在没有指定 spring bean 名称的情况下完美运行。 这是一个简单的例子:

@RestController
@RequestMapping("/v1/mycontroller")
public class MyControllerV1 {
    
    @RequestMapping("/mymethod1")
    public Object mymethod1(@RequestBody Object myRequest) {
        <my v1 implementation>
        return .....
    }
    
    @RequestMapping("/mymethod2")
    public Object mymethod2(@RequestBody Object myRequest) {
        <my v1 implementation>
        return .....
    }
}



@RestController
@RequestMapping("/v2/mycontroller")
public class MyControllerV2 extends MyControllerV1 {
    
    @RequestMapping("/mymethod1")
    public Object mymethod1(@RequestBody Object myRequest) {
        <my v2 implementation>
        return .....
    }
    
}

在这种情况下,您可以通过两种不同的方式调用“mymethod1”和“mymethod2”,它们是

http://hostname/v1/mycontroller/mymethod1 <-- 第一个实现-->

http://hostname/v2/mycontroller/mymethod1 <-- 第二个实现-->

http://hostname/v1/mycontroller/mymethod2 <-- 相同的实现-->

http://hostname/v2/mycontroller/mymethod2 <-- 相同的实现 -->

“mymethod1”有两种不同的实现,而“mymethod2”只有一种“MyControllerV1”继承自“MyControllerV2”的实现

您不仅不能以这种方式共享映射,而且继承似乎根本不适用于@RestController 这样做会导致您的控制器默默地无法获取您的任何@RequestMapping注释方法。 弄清楚这一点需要花费相当长的时间,但是您可以检查日志文件的输出以获取它不工作的提示。 具体来说,如果您没有看到AbstractHandlerMethodMapping为您的@RestController打印的以下日志行,您就会知道您的方法处理@RestController

    if (logger.isDebugEnabled()) {
        logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM