2010-03-23 9 views
36

Estoy tratando de implementar URLs RESTful en mi aplicación Spring MVC. Todo está bien excepto para el envío de formularios. Necesito redireccionar al formulario original o a una página de "éxito".Spring MVC Controller redirige usando parámetros de URL en lugar de en respuesta

@Controller 
@RequestMapping("/form") 
public class MyController { 

    @RequestMapping(method = RequestMethod.GET) 
    public String setupForm() { 
     // do my stuff 
     return "myform"; 
    } 

    @RequestMapping(method = RequestMethod.POST) 
    public String processForm(ModelMap model) {    
     // process form data 

     model.addAttribute("notification", "Successfully did it!"); 
     return "redirect:/form"; 
    } 
} 

Sin embargo, como he leído en el Spring documentation, si redirige ningún parámetro se pondrán en la url. Y eso no funciona para mí. ¿Cuál sería la forma más elegante de esto?

+0

¿Qué URL de redireccionamiento quieres conseguir? – skaffman

+0

Realmente no importa, solo tengo que redireccionar después de procesar los datos de la publicación en una página y notificar al usuario que lo que presentaron se procesó correctamente. Parece que esta es una solicitud común http://jira.springframework.org/browse/SPR-1294. Pero podría no solucionarse por un tiempo. – predhme

+0

En realidad, no parece que ninguno de los arreglos descritos en los dos tickets relacionados resuelvan su problema en particular: uno de ellos trata de controlar qué atributos del modelo están expuestos como cadenas de consulta (pero aún así expondrá algunos) y el otro consiste en agregar atributos como parte de la ruta de la url (que es agradablemente relajante para los ID, por ejemplo, pero aún no le da un lugar para llevar un mensaje de éxito). –

Respuesta

7

http://jira.springframework.org/browse/SPR-6464 me proporcionó lo que necesitaba para que las cosas funcionen hasta que Spring MVC ofrezca la funcionalidad (potencialmente en la versión 3.0.2). Aunque simplemente implementé las clases que tenían temporalmente y agregué el filtro al contexto de mi aplicación web. ¡Funciona genial!

+1

Al igual que una actualización, esta funcionalidad está programada para Spring 3.1 – predhme

+2

Y de hecho se implementa en Spring 3.1. – praseodym

+1

El enlace está roto. –

8

Puede tener processForm() devolver un objeto Ver en su lugar, y hacer que devuelva el tipo concreto RedirectView que tiene un parámetro para setExposeModelAttributes().

Al devolver el nombre de la vista con el prefijo "redirect:", Spring MVC transforma a un objeto RedirectView todos modos, sólo lo hace con setExposeModelAttributes a verdadero (que creo que es un valor impar por defecto a).

+0

Si el mensaje de éxito no se expone como una cadena de consulta, ¿cómo llega a la vista redirigida? –

+0

Eso es lo que me preguntaba. – predhme

+0

¿Cómo quieres que llegue a la página de éxito? Si desea hacer una redirección, parece que necesita pasarla como parámetro de solicitud o puede configurarla en la sesión y eliminarla en la página siguiente. Pero tiene que ser pasado de alguna manera. –

4

Si no desea el mensaje correcto en la URL, entonces una opción es colocarlo en la sesión (en el método processForm) y luego verificarlo (y eliminarlo) en el método setupForm.

Editado para agregar: si esto es un dolor hacerlo manualmente, entonces podría escribir una subclase de RedirectView que agregue un atributo de "mensaje" y envuelva el proceso de insertarlo en la sesión. No estoy seguro, sin embargo, si hay una manera fácil de envolver el mensaje de salida de la sesión ...

Honestamente, no creo que haya una respuesta fácil: la naturaleza de una redirección HTTP es ese estado isn llevado por más; Si desea mantener el estado de todos modos, está atrapado con las diversas formas habituales de mantener el estado en las aplicaciones web: la sesión, una cookie, una cadena de consulta ...

+0

Ciertamente posible, pero como mi aplicación es mucho más grande que solo una, resulta bastante molesto tener que hacer eso para cada forma. – predhme

+0

Struts parece ofrecer algo llamado ActionMessages. No estoy del todo seguro de qué se trata. Además, con Ruby On Rails, ofrecen un flash [: notificación]. Que es esencialmente lo que estoy tratando de lograr. El mensaje flash se almacena hasta la siguiente acción (redireccionamiento resultante o lo que sea). Parece que http://www.jroller.com/raible/entry/migrating_from_struts_to_spring intentó abordar esto. Su camino parece interesante. – predhme

+0

Bueno, me parece que su enfoque es básicamente envolver la sesión y poner el mensaje en la sesión, en la línea de lo que tenía en mente. Pero él da el código real, por lo que ciertamente es más útil. –

30

Tuve el mismo problema. resuelto de esta manera:

return new ModelAndView("redirect:/user/list?success=true"); 

Y entonces mi método de controlador de aspecto:

public ModelMap list(@RequestParam(required=false) boolean success) { 
    ModelMap mm = new ModelMap(); 
    mm.put(SEARCH_MODEL_KEY, campaignService.listAllCampaigns()); 
    if(success) 
     mm.put("successMessageKey", "campaign.form.msg.success"); 
    return mm; 
} 

funciona perfectamente a menos que desee enviar datos simples, no digamos colecciones. Entonces tendrías que usar la sesión, supongo.

9

Este problema está causado (como han indicado otros) por los atributos del modelo que persisten en la cadena de consulta; esto generalmente no es deseable y corre el riesgo de crear agujeros de seguridad y cadenas de consulta ridículas.Mi solución habitual es nunca utilizar cuerdas de redirecciones en Spring MVC, en lugar de utilizar un RedirectView que puede ser configurado para no exponer atributos modelo (ver: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html)

RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes) 

Así que tienden a tener un método util que hace un 'redireccionamiento seguro' como:

public static RedirectView safeRedirect(String url) { 
    RedirectView rv = new RedirectView(url); 
    rv.setExposeModelAttributes(false); 
    return rv; 
} 

La otra opción es utilizar XML de configuración de frijol:

<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView"> 
    <property name="exposeModelAttributes" value="false" /> 
    <property name="url" value="/myRedirect"/> 
</bean> 

Una vez más, usted podría abstracta esto en su propia clase para evitar la repetición (p. SafeRedirectView).


Una nota acerca de 'despejar el modelo' - esto no es lo mismo que 'no exponer el modelo' en todas las circunstancias. Un sitio en el que trabajé tenía muchos filtros que agregaban cosas al modelo, esto significaba que borrar el modelo antes de redireccionar no evitaría una larga cadena de consulta. También sugeriría que "no exponer los atributos del modelo" es un enfoque más semántico que "borrar el modelo antes de redireccionar".

+0

RedirectView: la redirección segura funcionó para mí. Gracias MatCarey! –

3

Hey sólo puede hacer una cosa sencilla en lugar de utilizar el modelo para enviar el uso de parámetros HttpServletRequest objeto y hacerlo

HttpServletRequest request; 
request.setAttribute("param", "value") 

ahora sus parametros no se mostrarán en el encabezado URL espero que funcione :)

0
@RequestMapping(path="/apps/add", method=RequestMethod.POST) 
public String addApps(String appUrl, Model model, final RedirectAttributes redirectAttrs) { 
    if (!validate(appUrl)) { 
     redirectAttrs.addFlashAttribute("error", "Validation failed"); 
    } 
    return "redirect:/apps/add" 
} 

@RequestMapping(path="/apps/add", method=RequestMethod.GET) 
public String addAppss(Model model) { 
    String error = model.asMap().get("error"); 
} 
Cuestiones relacionadas