Spring-MVC问题在实现接口的控制器上使用@Controller

时间:2020-03-06 14:56:07  来源:igfitidea点击:

我正在使用spring 2.5和注释来配置spring-mvc Web上下文。不幸的是,我无法执行以下操作。我不确定这是否是一个错误(似乎是错误的),或者对于注释和接口实现子类的工作方式是否存在基本的误解。

例如,

@Controller
@RequestMapping("url-mapping-here")
public class Foo {
  @RequestMapping(method=RequestMethod.GET)
  public void showForm() {
    ...
  }
  @RequestMapping(method=RequestMethod.POST)
  public String processForm() {
  ...
  }
}

工作正常。当上下文启动时,将发现此处理程序处理的url,并且一切正常。

但是,这不会:

@Controller
@RequestMapping("url-mapping-here")
public class Foo implements Bar {
  @RequestMapping(method=RequestMethod.GET)
  public void showForm() {
    ...
  }
  @RequestMapping(method=RequestMethod.POST)
  public String processForm() {
  ...
  }
}

当我尝试提取URL时,出现以下令人讨厌的堆栈跟踪:

javax.servlet.ServletException: No adapter for handler [com.shaneleopard.web.controller.RegistrationController@e973e3]: Does your handler implement a supported interface like Controller?
    org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1091)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:627)

但是,如果我将Bar更改为抽象超类并让Foo对其进行扩展,则它将再次起作用。

@Controller
@RequestMapping("url-mapping-here")
public class Foo extends Bar {
  @RequestMapping(method=RequestMethod.GET)
  public void showForm() {
    ...
  }
  @RequestMapping(method=RequestMethod.POST)
  public String processForm() {
  ...
  }
}

这似乎是一个错误。 @Controller注释应足以将其标记为控制器,并且我应该能够在控制器中实现一个或者多个接口,而无需执行其他任何操作。有任何想法吗?

解决方案

毫无疑问,批注和继承会有些棘手,但我认为这应该可行。尝试将AnnotationMethodHandlerAdapter显式添加到servlet上下文中。

http://static.springframework.org/spring/docs/2.5.x/reference/mvc.html#mvc-ann-setup

如果这不起作用,那么多一点信息将有所帮助。具体来说,接口中有两种带注释的控制器方法吗? Foo应该是RegistrationController吗?

埃德是对的,补充

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

工作正常

我需要做的是更换

<tx:annotation-driven/>

<tx:annotation-driven  proxy-target-class="true"/>

这迫使Aspectj使用CGLIB代替动态代理来执行方面CGLIB不会丢失注释,因为它扩展了类,而动态代理只是公开了已实现的接口。

我们需要使用'proxy-target-class =" true"'的真正原因是在DefaultAnnotationHandlerMapping#determineUrlsForHandler()方法中:尽管它使用ListableBeanFactory#findAnnotationOnBean来查找@ RequestMapping`注释(这需要关心任何代理问题),使用@ AnnotationUtils#findAnnotation(不会处理代理问题)来完成对@Controller批注的添加查找。