Spring-MVC问题在实现接口的控制器上使用@Controller
我正在使用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批注的添加查找。