2011-02-04 18 views
140

Con Spring 3.0, ¿puedo tener una variable de ruta opcional?Con Spring 3.0, ¿puedo crear una variable de ruta opcional?

Por ejemplo

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET) 
public @ResponseBody TestBean testAjax(
     HttpServletRequest req, 
     @PathVariable String type, 
     @RequestParam("track") String track) { 
    return new TestBean(); 
} 

Aquí me gustaría /json/abc o /json a llamar al mismo método.
Una solución obvia declarar type como un parámetro de la petición:

@RequestMapping(value = "/json", method = RequestMethod.GET) 
public @ResponseBody TestBean testAjax(
     HttpServletRequest req, 
     @RequestParam(value = "type", required = false) String type, 
     @RequestParam("track") String track) { 
    return new TestBean(); 
} 

y luego /json?type=abc&track=aa o /json?track=rr funcionará

Respuesta

147

No se puede tener variables de ruta opcionales, pero se puede tener dos métodos de controlador que requieren la misma código de servicio:

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET) 
public @ResponseBody TestBean typedTestBean(
     HttpServletRequest req, 
     @PathVariable String type, 
     @RequestParam("track") String track) { 
    return getTestBean(type); 
} 

@RequestMapping(value = "/json", method = RequestMethod.GET) 
public @ResponseBody TestBean testBean(
     HttpServletRequest req, 
     @RequestParam("track") String track) { 
    return getTestBean(); 
} 
+0

Esta es sin duda una buena manera de hacerlo. – Shamik

+3

@Shamik: Esta es una razón convincente * no * para usar variables de ruta, en mi opinión. La proliferación combinatoria puede irse rápidamente de las manos. – skaffman

+7

En realidad, no porque la ruta no puede ser tan compleja mientras se llena con componentes opcionales. Si tiene más de uno o un máximo de dos elementos de ruta opcionales, considere seriamente cambiar algunos de ellos para solicitar parámetros. –

20

Se puede usar un:

@RequestParam(value="somvalue",required=false) 

de parametros opcionales en lugar de un pathVariable

+1

Parece una versión específica. No ir para la primavera 3. –

+4

Actualmente, se utiliza este método para un proyecto de primavera 3.1, y los documentos dicen que funciona para 2.5+, por lo que definitivamente funciona para Spring 3. EDIT: [fuente] (http: //static.springsource. org/spring/docs/3.0.x/api/org/springframework/web/bind/annotation/RequestParam.html). –

+18

Cierto, pero de eso no se trata la pregunta. El uso de los parámetros * request * se menciona en la pregunta como * "Una solución obvia" *, pero la pregunta en sí tiene que ver con los parámetros * path *. Esta no es una solución para los parámetros de ruta opcionales. – Arjan

69

No es bien sabido que también puede inyectar un Mapa de las variables de ruta utilizando la anotación @PathVariable. No estoy seguro de si esta función está disponible en la primavera de 3.0 o si se añadió más tarde, pero aquí es otra manera de resolver el ejemplo:

@RequestMapping(value={ "/json/{type}", "/json" }, method=RequestMethod.GET) 
public @ResponseBody TestBean typedTestBean(
    @PathVariable Map<String, String> pathVariables, 
    @RequestParam("track") String track) { 

    if (pathVariables.containsKey("type")) { 
     return new TestBean(pathVariables.get("type")); 
    } else { 
     return new TestBean(); 
    } 
} 
+1

gracias, en la primavera 4.2 funciona como esperaba – Edgar

+0

Lo uso todo el tiempo. Esto es útil cuando quiero un único método para manejar diferentes tipos de uri ex: {"/ json/{type}", "/ json/{type}/{xyz} ","/json/{type}/{abc} ","/json/{type}/{abc}/{something} ","/json "} – Vaibs

-3
$.ajax({ 
      type : 'GET', 
      url : '${pageContext.request.contextPath}/order/lastOrder', 
      data : {partyId : partyId, orderId :orderId}, 
      success : function(data, textStatus, jqXHR) }); 

@RequestMapping(value = "/lastOrder", method=RequestMethod.GET) 
public @ResponseBody OrderBean lastOrderDetail(@RequestParam(value="partyId") Long partyId,@RequestParam(value="orderId",required=false) Long orderId,Model m) {} 
+3

Es posible que desee editar en algún texto en su respuesta, explicando * por qué * cree que esto contribuye a resolver el problema (4 años más tarde). – Qirel

+0

No ayudaría. La respuesta es completamente incorrecta. – Phil

67

Si está utilizando Primavera 4.1 y Java 8 se puede utilizar java.util.Optional que se apoya en @RequestParam, @PathVariable, @RequestHeader y @MatrixVariable en Spring MVC -

@RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET) 
public @ResponseBody TestBean typedTestBean(
    @PathVariable Optional<String> type, 
    @RequestParam("track") String track) {  
    if (type.isPresent()) { 
     //type.get() will return type value 
     //corresponds to path "/json/{type}" 
    } else { 
     //corresponds to path "/json" 
    }  
} 
+0

¿Seguro que esto funcionaría? Su propia respuesta [aquí] (http://stackoverflow.com/a/34670775/1345021) sugiere que el controlador no se golpeará si {type} está ausente de la ruta. Creo que PathVariable Map sería un mejor enfoque, o usar controladores separados. –

+3

Sí, si solo tienes '"/json/{tipo} "' y el tipo no está presente, no se ejecutará (como mi respuesta enlazada sugiere) pero aquí tienes 'value = {"/json/{type} ", "/ json"} '. Por lo tanto, si alguien coincide con el método del controlador se golpeará. –

+0

¿Es posible que el mismo valor, etc., sea RequestParam y RequestParam también? – zygimantus

Cuestiones relacionadas