Spring调用错误的控制器映射

时间:2012-08-08 09:33:01

标签: java validation tomcat spring-mvc

我正在使用Spring构建非常基本的mvc应用程序。它有一个控制器应该在请求体上调用验证。问题是,如果我在web.xml中定义映射,它就会停止找到正确的控制器,但是当我修改servlet应用程序上下文时,Spring会立即生成一些新的绑定,但这次基于注释的验证将被忽略。如何在仍然调用基于注释的验证的同时在web.xml中控制映射?

以下是详细信息:

控制器:

@Controller
@RequestMapping("/api")
public class UserActionsController {

    @RequestMapping(value="/choice", method = RequestMethod.POST)
    public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action)
    {       
        return action;
    }
}

这是servlet应用程序上下文:

<mvc:annotation-driven/>

<context:component-scan base-package="com.my.package" />

<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
        </map>
    </property>
    <property name="defaultContentType" value="application/json" />
    <property name="defaultViews">
        <list>
            <bean
                class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
        </list>
    </property>
</bean>

Web xml:

<servlet>
    <servlet-name>action-api</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>action-api</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

上面的配置正在运行。当我尝试更改web.xml时,问题就开始了,因此控制器只负责“/ api / *”。我将其更改为<url-pattern>/api/*</url-pattern>。在那种情况下,Spring无法找到合适的控制器。

(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice]
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice]
(PageNotFound:1080) - No mapping found for HTTP request with URI [/api/choice] in DispatcherServlet with name 'action-api'
(DispatcherServlet:913) - Successfully completed request

修改servlet应用程序上下文有帮助,Spring现在能够找到控制器,但不再调用验证。

<bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="alwaysUseFullPath" value="true" />
    <property name="messageConverters">
        <util:list id="beanList">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
        </util:list>
    </property>
</bean>

<bean
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="alwaysUseFullPath" value="true" />
</bean>

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="alwaysUseFullPath" value="true" />
</bean>

这是日志:

(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice]
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice]
(DefaultAnnotationHandlerMapping:124) - Mapping [/api/choice] to HandlerExecutionChain with handler [com.my.package.controller.UserActionsController@1f86dbd] and 1 interceptor
(HandlerMethodInvoker:638) - Reading [com.my.package.model.NameValue] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@2059ef]
(HandlerMethodInvoker:173) - Invoking request handler method: public com.my.package.model.NameValue com.citypath.dima.controller.UserActionsController.addUserChoice(com.my.package.model.NameValue)
(AnnotationMethodHandlerAdapter:1037) - Written [com.my.package.model.NameValue@166685b] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@2059ef]
(DispatcherServlet:957) - Null ModelAndView returned to DispatcherServlet with name 'action-api': assuming HandlerAdapter completed request handling
(DispatcherServlet:913) - Successfully completed request

看起来Spring正在进行一些绑定,但这次验证器被忽略了。 我需要有2个控制器,比如'/ api'和'/ something'。如何在web.xml中定义它,以便Spring能够找到它们并调用验证?

感谢。

3 个答案:

答案 0 :(得分:7)

Spring @Controllers URL总是相对于处理它们的Spring Dispatcher Servlet进行解释。因此,如果您将调度程序servlet映射到web.xml中的/ api / *,那么上面控制器的URL是/ api / api / choice

因此,您可以在web.xml中配置两个spring dispatcher servelts,一个映射到web.xml中的/ api,另一个映射到web.xml中的/ somethingelse,然后您可以从@RequestMappings中删除/ api

在我的应用程序中,我使用了一个用于api和UI的Dispatcher Servlet,我在各种API控制器中使用名为URL的公共静态最终字符串来构建API所公开的各种资源的路径。以下是我的API中的示例。

@Controller
@RequestMapping(CompanyPermissionsResourceController.PATH)
public class CompanyPermissionsResourceController extends BaseApiController
{
    public static final String PATH = CompanyResourceController.PATH + "/permissions"; 

答案 1 :(得分:1)

您确定要向post提出/api/choice请求吗?

@RequestMapping(value="/choice", method = RequestMethod.POST)

尝试更改为

@RequestMapping(value="/choice", method = RequestMethod.GET)
public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action)
{       
    return action;
}

答案 2 :(得分:-1)

我不认为它是这样的。将所有路径/api/choice放在方法级别。