2012-08-08 10 views
5

Estoy construyendo una aplicación de mvc muy básica con Spring. Tiene un controlador que debe invocar la validación en el cuerpo de la solicitud. El problema es que si defino la asignación en web.xml deja de encontrar el controlador correcto, pero cuando modifico el contexto de la aplicación de servlet Spring Star, hago algunos enlaces nuevos sobre la marcha, pero esta vez la anotación basada en la anotación se ignora. ¿Cómo puedo controlar las asignaciones en web.xml mientras sigo invocando la validación basada en anotaciones?El resorte invoca la asignación incorrecta del controlador

Aquí están los detalles:

El controlador:

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

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

Este es el contexto de aplicación 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> 

XML Web:

<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> 

La configuración anterior está funcionando. El problema comienza cuando intento cambiar web.xml, por lo que el controlador solo será responsable de "/ api/*". Lo cambio a <url-pattern>/api/*</url-pattern>. En ese caso, Spring no puede encontrar el controlador correcto.

(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 

Modificación del contexto de aplicación servlet ayuda, Primavera ahora capaz de encontrar el controlador, pero la validación no se invoca nunca más.

<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> 

Aquí está el registro:

(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 [[email protected]] and 1 interceptor 
(HandlerMethodInvoker:638) - Reading [com.my.package.model.NameValue] as "application/json" using [org.springf[email protected]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 [[email protected]] as "application/json;charset=UTF-8" using [org.springf[email protected]2059ef] 
(DispatcherServlet:957) - Null ModelAndView returned to DispatcherServlet with name 'action-api': assuming HandlerAdapter completed request handling 
(DispatcherServlet:913) - Successfully completed request 

Parece que la primavera a hacer algo de unión sobre la marcha, pero esta vez los validadores son ignorados. Necesito tener 2 controladores para, digamos '/ api' y '/ algo'. ¿Cómo puedo definirlo en web.xml para que Spring pueda ubicarlos e invocar la validación?

Gracias.

Respuesta

7

Spring @Controllers Las URL se interpretan siempre en relación con el Servlet Spring Dispatcher que las maneja. Por lo tanto, si asigna el servlet despachador a/api/* en web.xml, la URL de su controlador anterior es/api/api/choice

Puede configurar dos servidores de distribución de muelles en web.xml uno asignado a/api en el web.xml y uno asignado a/somethingelse en web.xml entonces usted puede simplemente eliminar/api del @RequestMappings

En mi aplicación estoy usando un Servlet Dispatcher para api y UI y utilizo public static Cadena final llamada URL en mis diversos controladores API para construir las rutas a los diversos recursos expuestos por la API. A continuación hay un ejemplo de mi API.

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

Gracias. El '/ api/api/choice' realmente me ayudó a entender por qué Spring no pudo encontrar el controlador. Si no defino la parte 'api' en el controlador, solo en web.xml todo funciona muy bien. Incluso mapeo a nivel de controlador y método. Justo como supone que funcione. – Dima

+0

Esta respuesta me ayudó a encontrar la causa raíz de mi problema que era mi @ComponentScan no incluía el paquete de mi controlador – McLovin

1

¿Estás seguro de que estás haciendo post solicitud a /api/choice?

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

intente cambiar a

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

Como mencioné, la primera configuración funciona. Entonces no hay problemas en el lado del cliente. (Estoy usando Fiddler, que está totalmente bien) – Dima

-1

creo que no funciona así. Pon toda la ruta /api/choice en el nivel del método.

+0

¿Puedes explicar por qué no funciona? Hay soporte para el nivel de controlador @RequestMapping. Y funciona bien cuando web.xml no especifica ninguna ruta además de/* – Dima

+0

. Creo que Spring simplemente no agrega rutas de RequestMapping a nivel de clase a RequestMapping en el nivel de método. Por supuesto, puedo estar equivocado. Nunca intenté este enfoque. Debe definir RequestMapping en el nivel del método para que funcione, de seguro. No tiene que parametrizarse con la ruta si tiene RequestMapping parametrizado con la ruta en el nivel de clase. La pregunta es: ¿necesitas este enfoque para algo? –

+0

Y ahora sé que estaba equivocado. :) –

Cuestiones relacionadas