在控制器上使用@Controller实现接口的Spring-MVC问题
我使用spring 2.5和annotations来配置我的spring-mvc web上下文。不幸的是,我无法得到以下的工作。我不确定这是一个错误(看起来像是这样),还是对注释和接口实现子类的工作原理有一个基本的误解。在控制器上使用@Controller实现接口的Spring-MVC问题
例如,
@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() {
...
}
}
当我试图拉起网址,我得到以下讨厌的堆栈跟踪:
javax.servlet.ServletException: No adapter for handler [[email protected]]: 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)
但是,如果我改变酒吧是一个抽象超类并让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 proxy-target-class="true"/>
这种力量的AspectJ使用CGLIB代替
<tx:annotation-driven/>
用于做方面而不是dy标记代理 - CGLIB不会丢失注释,因为它扩展了类,而动态代理只是公开实现的接口。
你需要使用“代理目标类=‘真’”是DefaultAnnotationHandlerMapping#determineUrlsForHandler()
方法的真正原因是:尽管它使用ListableBeanFactory#findAnnotationOnBean
用于查找一个@RequestMapping
注释(这大约需要任何代理问题护理),附加为@Controller
注释查找使用AnnotationUtils#findAnnotation
完成(不把手代理问题)
你的意思是有一个错误? – Ruslan 2017-07-19 11:04:40
如果您想使用的接口为您的Spring MVC控制器,那么你需要走动了一下注解,如在Spring文档中提到:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping
使用@RequestMapping On接口方法当应用 功能需要为控制器对象 (例如,创建代理)时发生 处理注释控制器类时的常见错误。 @Transactional方法)。通常,您将为控制器引入一个接口 ,以便使用JDK动态代理。要使此 正常工作,必须将@RequestMapping注释移动到接口 ,以及映射机制只能“看到” 代理公开的接口。或者,您可以在适用于控制器 (在我们的交易场景中)的功能配置中激活proxy-target-class =“true” 。这样做 表示应该使用基于CGLIB的子类代理,而不是基于接口的JDK代理使用 。关于各种代理 机制的更多信息,请参见第8.6节“代理机制”。
遗憾的是它并没有给这一个具体的例子。我已经找到了设置这样工作的:
@Controller
@RequestMapping(value = "/secure/exhibitor")
public interface ExhibitorController {
@RequestMapping(value = "/{id}")
void exhibitor(@PathVariable("id") Long id);
}
@Controller
public class ExhibitorControllerImpl implements ExhibitorController {
@Secured({"ROLE_EXHIBITOR"})
@Transactional(readOnly = true)
@Override
public void exhibitor(final Long id) {
}
}
所以,你必须在这里那是什么声明@Controller,@PathVariable和@RequestMapping注解(Spring的MVC注释),然后你可以把你的接口@例如在具体类上的Transactional或@Secured注释。由于Spring的映射方式,只需要将@Controller类型注释放在界面上即可。
请注意,如果您使用接口,则只需执行此操作。如果您对CGLib代理感到满意,则不一定需要这样做,但如果由于某种原因想要使用JDK动态代理,则可能需要这样做。
我知道这是为时已晚,但我写这篇文章的人有这个问题 如果您正在使用基于注解配置...的解决办法是这样的:
@Configuration
@ComponentScan("org.foo.controller.*")
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig { ...}
所需注意的是CGLIB是相当不赞成的。 – 2015-07-28 15:44:53