6

我执行重构并将控制器拆分为 2 个控制器:

@RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="first")

在第一个控制器中,并且:

@RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="second")

在第二个控制器中,因此这些注释位于不同的文件中。当我构建和使用项目时,一切都很好(我在表单中输入了不同名称的 HTML 标签:firstsecond)。

但是当我尝试运行 JUnit 控制器测试时:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-context.xml" })

我得到跟踪:

引起:java.lang.IllegalStateException:无法映射处理程序'firstController'
  到 URL 路径 [/graph.htm]:已经有处理程序
  类型 [class com.web.controller.SecondController] 映射。
    在 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:294)
    在 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:266)
    在 org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.detectHandlers(AbstractDetectingUrlHandlerMapping.java:82)
    在 org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.initApplicationContext(AbstractDetectingUrlHandlerMapping.java:58)
    在 org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)
    在 org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:72)
    在 org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
    在 org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:117)
    在 org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:92)
    在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:399)
    在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
    在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)

当我注释掉这个时:

@RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="second")

在第二个控制器中,第一个控制器的单独测试成功完成。

要解决此问题,我可能会使用不同的 URL(@RequestMapping中的),但我不明白为什么在我的应用程序的生产构建中为参数解析请求映射并因SpringJUnit4ClassRunner失败。

欢迎任何帮助!

附言。我使用 Spring 3.2。

聚苯乙烯。我发现几乎相同的问题我可以在不同的 Spring 控制器中使用不同的参数具有相同的映射值吗?但根据答案,我的生产构建也必须失败?!但我成功运行生产构建!

另请参阅:

*PPS

我查看 3.2 的官方文档:

http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#params%28%29

在 Servlet 环境中,参数映射被视为限制
在类型级别强制执行。主路径映射(即
指定的 URI 值)仍然必须唯一标识目标处理程序,其中
参数映射仅表示调用处理程序的先决条件。

所以似乎我执行了非法编码练习......

4

2 回答 2

3

这是我在阅读您的问题中引用的官方文档时所理解的:

在 Servlet 环境中,参数映射被视为在类型级别强制执行的限制。主路径映射(即指定的 URI 值)仍然必须唯一标识中的目标处理程序,参数映射仅表示调用处理程序的先决条件。

我添加了“在课堂内”这几个词。

请注意在类型级别强制执行。据我了解,这意味着:在 servlet 环境中。在方法级别声明参数与在类型级别声明参数完全相同(至少如果您的类中只有一个方法)。

最后,如果您注意这句话(相同来源):

在类型级别使用时,所有方法级别映射都继承此参数限制(即,在处理程序方法被解析之前检查类型级别限制)。

我认为所有这些总结了为什么您没有进行非法编码

关于单元测试:

这里同样重要的是“在 Servlet 环境中”这句话。显然,在运行单元测试时:你不在Servlet 环境中,这可能就是它失败的原因。

于 2013-01-28T13:17:09.777 回答
2

我的邻居同事帮我解决了调试问题。

我们比较了生产环境和测试环境,发现上下文 XML 配置存在差异。

先前失败的测试配置:

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

新的和有效的测试上下文配置:

    <bean name="handlerMapping"
          class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean name="handlerAdapter"
          class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

不同的 spring 类使用不同的映射模式。每个类的旧用途,每个方法的新用途!

于 2013-01-28T13:35:28.360 回答