2009-05-12 12 views
5

Estoy tratando de exponer un servicio REST completo (alojado por Tomcat) y no puedo averiguar cuál es la configuración requerida para Spring 3 (M3).¿Cuál es la configuración mínima para el servicio REST-completamente anotado construido en Spring 3 (m3)?

Esta es la forma (ejemplo) el servicio será similar a:

@Controller 
@Scope("prototype") 
public class UsersController 
{ 
    @RequestMapping(value="https://stackoverflow.com/users/hello", method=RequestMethod.GET) 
    public String hello() 
    { 
     return "hello, user!"; 
    } 
} 

La configuración de Spring que tengo es el siguiente (Omito los nombres de clase completos por simplicidad):

<beans ...> 
    <context:annotation-config /> 
    <bean class="...AutowiredAnnotationBeanPostProcessor"/> 
    <bean class="...DefaultAnnotationHandlerMapping"> 
    <context:component-scan base-package="com.mycompany.myserver"/> 
</beans> 

Este es cómo he enchufado mi configuración de Spring en web.xml:

<listener> 
      <listener-class>...RequestContextListener</listener-class> 
    </listener> 
    <!-- Servlets --> 
    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>...DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>classpath:*:dispatcher-servlet.xml</param-value> 
     </init-param> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>/services/*</url-pattern> 
    </servlet-mapping> 

Tenga en cuenta que estoy tratando de crea una configuración mínima (sin archivos servlet-config.xml adicionales). Es por eso que estoy señalando el Dispatcher a una configuración incorporada.

¿Es esto correcto?

Después de empezar Tomcat y todos los granos están cargados estoy dirigen a la siguiente URL: "¡Hola, el usuario"

http://localhost:8080/myserver/services/users/hello 

Y, en lugar de la responder, a mi pesar, veo los errores siguientes en el archivo de registro:

09:54:45,140 DEBUG RequestContextListener:69 - Bound request context to thread: [email protected] 
09:54:45,140 DEBUG DispatcherServlet:834 - DispatcherServlet with name 'dispatcher' determining Last-Modified value for [/myserver/services/users/hello] 
09:54:45,156 DEBUG DefaultAnnotationHandlerMapping:178 - Mapping [/users/hello] to handler '[email protected]' 
09:54:45,171 DEBUG DispatcherServlet:850 - Last-Modified value for [/myserver/services/users/hello] is: -1 
09:54:45,171 DEBUG DispatcherServlet:683 - DispatcherServlet with name 'dispatcher' processing GET request for [/myserver/services/users/hello] 
09:54:45,218 DEBUG HandlerMethodInvoker:148 - Invoking request handler method: public java.lang.String com.symantec.repserver.myserver.UsersController.hello() 
09:54:45,218 DEBUG DefaultListableBeanFactory:1366 - Invoking afterPropertiesSet() on bean with name 'hello, user!' 
09:54:45,218 DEBUG DispatcherServlet:1060 - Rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'hello, user!'; URL [hello, user!]] in DispatcherServlet with name 'dispatcher' 
09:54:45,234 DEBUG InternalResourceView:237 - Forwarding to resource [hello, user!] in InternalResourceView 'hello, user!' 
09:54:45,250 DEBUG DispatcherServlet:834 - DispatcherServlet with name 'dispatcher' determining Last-Modified value for [/myserver/services/users/hello, user!] 
09:54:45,250 DEBUG DispatcherServlet:842 - No handler found in getLastModified 
09:54:45,250 DEBUG DispatcherServlet:683 - DispatcherServlet with name 'dispatcher' processing GET request for [/myserver/services/users/hello, user!] 
09:54:45,250 WARN PageNotFound:959 - No mapping found for HTTP request with URI [/myserver/services/users/hello, user!] in DispatcherServlet with name 'dispatcher' 
09:54:45,250 DEBUG DispatcherServlet:643 - Successfully completed request 
09:54:45,250 DEBUG DispatcherServlet:643 - Successfully completed request 
09:54:45,250 DEBUG RequestContextListener:89 - Cleared thread-bound request context: [email protected] 

Como se observa, mi configuración actual está tratando de desviar esta solicitud como una nueva solicitud:

/myserver/services/users/hello, user! 

Cualquier idea ¿qué está mal? ¿Qué me estoy perdiendo?

Respuesta

1

La cuestión es su hola() es anotado como un handlerMethod de primavera y por la documentación @RequestMapping, métodos de controlador puede devolver cualquier número de objetos, pero si se devuelve una cadena a continuación:

@Request Documentation

A Valor de cadena que se interpreta como nombre de vista, con el modelo determinado implícitamente a través de objetos de comando y métodos de acceso de datos de referencia anotados ModelAttribute. El método de control también puede enriquecer mediante programación el modelo declarando un argumento ModelMap (ver más arriba)

por lo que es, básicamente, en busca de la asignación para esa cadena que regrese 'hola, el usuario' - que no existe. Puede hacer que su método sea nulo y, dentro del método, escribirlo usted mismo en HttpServletResponse.

respuesta adicional:

@RequestMapping(value="https://stackoverflow.com/users/hello", method=RequestMethod.GET) 
public void hello(Writer w) { 
    w.write("hello, user!"); 
    w.flush(); 
    return; 
} 

Es posible que desee obtener toda la HttpServletResponse en lugar de sólo el escritor, de esa manera se pueden establecer las cabeceras HTTP apropiadas.

Disculpa, mi comentario más abajo es complicado, soy nuevo en este sitio.

+0

Hmm ... Pero está rompiendo toda la idea de JAX-RS, que afirma que el valor de retorno del método se envía a la parte solicitante. ¿Hay alguna manera de anotar mis métodos por lo que el requisito anterior será verdadero? – IgorM

+1

Según el método javadoc, su método toma un argumento de OutputStream o Writer que RequestMapper pasará en ServletOutputStream/Writer para que usted escriba. No estoy seguro de si esta es realmente la mejor manera de hacerlo, pero funcionará. @RequestMapping (value = "/ users/hello", method = RequestMethod.GET) public void hello (Writer w) { w.write ("hola, usuario!"); w.flush(); devolución; } Es posible que desee obtener todo el HttpServletResponse en lugar de simplemente Writer, de esa manera puede establecer los encabezados Http apropiados. – Gandalf

+0

Puede escribir la respuesta directamente a la secuencia tal como se sugirió anteriormente, o puede devolver un objeto ModelAndView que lo haga. El efecto es muy similar. Sería bueno si Spring 3 utilizara el nuevo patrón HttpMessageConverter para manejar valores de retorno de método, pero ssdly solo se aplica a @RequestBody. Los valores de retorno del método todavía se interpretan como en Spring 2.5 Recuerde que Spring REST MVC es * no * compatible con JAX-RS, eso fue una elección explícita que hicieron. JAX-RS simplemente no encajaba bien con Spring MVC. – skaffman

Cuestiones relacionadas