java - responsebody - spring mvc crud ajax
Spring MVC Controller redirige utilizando parámetros de URL en lugar de en respuesta (7)
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".
@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 leí en la documentación de Spring , si redirige los parámetros, se incluirán en la url. Y eso no funciona para mí. ¿Cuál sería la forma más elegante de esto?
Este problema está causado (como otros lo han expresado) 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 no utilizar nunca cadenas para redirecciones en Spring MVC, sino usar un RedirectView que se puede configurar para no exponer los atributos del 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 tiendo a tener un método util que hace una ''redirección segura'' como:
public static RedirectView safeRedirect(String url) {
RedirectView rv = new RedirectView(url);
rv.setExposeModelAttributes(false);
return rv;
}
La otra opción es usar XML de configuración de beans:
<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView">
<property name="exposeModelAttributes" value="false" />
<property name="url" value="/myRedirect"/>
</bean>
Nuevamente, puede abstraer esto en su propia clase para evitar la repetición (por ejemplo, SafeRedirectView).
Una nota sobre ''borrar 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".
Oye, puedes hacer una cosa simple en lugar de usar el modelo para enviar el parámetro, usar el objeto HttpServletRequest y hacer esto
HttpServletRequest request;
request.setAttribute("param", "value")
ahora sus parámetros no se mostrarán en su encabezado de URL espero que funcione :)
Puede hacer que processForm()
devuelva un objeto View en su lugar, y hacer que devuelva el tipo concreto RedirectView
que tiene un parámetro para setExposeModelAttributes()
.
Cuando devuelve un nombre de vista con el prefijo "redirect:"
, Spring MVC lo transforma en un objeto RedirectView
todos modos, simplemente lo hace con setExposeModelAttributes
en true (que creo que es un valor impar para el valor predeterminado).
Si no desea el mensaje de éxito en la URL, entonces una opción es ponerlo 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 algo difícil de hacer de forma manual, 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 que el estado no se transfiere; 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 ...
Yo tuve el mismo problema. lo resolvió así:
return new ModelAndView("redirect:/user/list?success=true");
Y luego mi método de controlador se ve así:
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 colecciones, digamos. Entonces tendrías que usar la sesión, supongo.
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!
@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");
}