validator validate mvc form custom constraint beans bean java spring google-app-engine spring-mvc validation

java - validate - Spring-Redirigir después de POST(incluso con errores de validación)



spring mvc validate form (7)

Además de la buena respuesta de Oscar, si está siguiendo ese enfoque de RedirectAttributes , no olvide que está pasando el modelAttribute a la página redirigida. Esto significa que si crea una nueva instancia de ese modeloAttribute para la página redirigida (en un controlador), perderá los errores de validación . Entonces, si su método de control POST es algo como esto:

@RequestMapping(value = "/submit", method = RequestMethod.POST) public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) { if (binding.hasErrors()) { attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding); attr.addFlashAttribute("register", register); return "redirect:/register/create"; } return "redirect:/register/success"; }

Entonces probablemente necesite hacer una modificación en su controlador de registro de página GET . De esto:

@RequestMapping(value = "/register/create", method = RequestMethod.GET) public String registerCreatePage(Model model) { // some stuff model.addAttribute("register", new Register()); // some more stuff }

a

@RequestMapping(value = "/register/create", method = RequestMethod.GET) public String registerCreatePage(Model model) { // some stuff if (!model.containsAttribute("register")) { model.addAttribute("register", new Register()); } // some more stuff }

Fuente: http://gerrydevstory.com/2013/07/11/preserving-validation-error-messages-on-spring-mvc-form-post-redirect-get/

Estoy intentando descubrir cómo "preservar" BindingResult para que pueda ser utilizado en un GET posterior a través de la etiqueta Spring <form:errors> . El motivo por el que quiero hacer esto es debido a las limitaciones de SSL de Google App Engine. Tengo un formulario que se muestra a través de HTTP y la publicación es a una URL HTTPS. Si solo reenvío en lugar de redireccionar, el usuario verá la https://whatever.appspot.com/my/form URL. Estoy tratando de evitar esto. ¿Alguna idea de cómo abordar esto?

A continuación se muestra lo que me gustaría hacer, pero solo veo errores de validación cuando uso return "create" .

@RequestMapping(value = "/submit", method = RequestMethod.POST) public final String submit( @ModelAttribute("register") @Valid final Register register, final BindingResult binding) { if (binding.hasErrors()) { return "redirect:/register/create"; } return "redirect:/register/success"; }


Desde Spring 3.1 puede usar RedirectAttributes. Agregue los atributos que desea tener disponibles antes de hacer la redirección. Agregue ambos, BindingResult y el objeto que está utilizando para validar, en este caso Register.

Para BindingResult, usará el nombre: "org.springframework.validation.BindingResult. [Name of your ModelAttribute]".

Para el objeto que está utilizando para validar, usará el nombre de ModelAttribute.

Para usar RedirectAttributes debes agregar esto en tu archivo de configuración. Entre otras cosas le está diciendo a Spring que use algunas clases más nuevas:

<mvc:annotation-driven />

Ahora los errores se mostrarán donde sea que esté redirigiendo

@RequestMapping(value = "/submit", method = RequestMethod.POST) public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) { if (binding.hasErrors()) { attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding); attr.addFlashAttribute("register", register); return "redirect:/register/create"; } return "redirect:/register/success"; }


El problema es que está redireccionando a un nuevo controlador, en lugar de representar la vista y devolver la página del formulario procesado. Tienes que hacer algo como:

String FORM_VIEW = wherever_your_form_page_resides ... if (binding.hasErrors()) return FORM_VIEW;

Mantendré las rutas fuera de cualquier método debido a la duplicación de cadenas de código.


La única forma de persistir objetos entre solicitudes (es decir, una redirección) es almacenar el objeto en un atributo de sesión. Por lo tanto, debe incluir "solicitud HttpServletRequest" en los parámetros del método para ambos métodos (es decir, get y post) y recuperar el objeto a través de request.getAttribute ("binding"). Dicho esto, y no lo he intentado por mí mismo, es posible que deba resolver cómo volver a vincular el enlace al objeto en la nueva solicitud.

Otra forma "menos agradable" es simplemente cambiar la URL del navegador usando javascript


Me preguntaría por qué necesitas la redirección. ¿Por qué no simplemente enviar a la misma URL y hacer que responda de manera diferente a un POST? Sin embargo, si realmente quieres hacer esto:

@RequestMapping(value = "/submit", method = RequestMethod.POST) public final String submit( @ModelAttribute("register") @Valid final Register register, final BindingResult binding, HttpSession session) { if (binding.hasErrors()) { session.setAttribute("register",register); session.setAttribute("binding",binding); return "redirect:/register/create"; } return "redirect:/register/success"; }

Luego, en tu método de "crear":

model.put("register",session.getAttribute("register")); model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));


No sé el problema exacto con Google App Engine, pero usar ForwardedHeaderFilter puede ayudar a preservar el esquema original que el cliente utilizó. Este filtro se agregó en Spring Framework 4.3, pero algunos contenedores Servlet proporcionan filtros similares y el filtro es autosuficiente, por lo que también puede obtener la fuente si es necesario.


Quizás esto es un poco simplista, pero ¿ha intentado agregarlo a su Modelo? Es decir, incluya el Modelo en los argumentos de su método y luego agregue BindingResult a él, que luego estará disponible en su vista.

model.addAttribute("binding",binding);

Creo que es posible que tengas que usar un reenvío en lugar de una redirección (en mi cabeza no recuerdo si una redirección pierde la sesión o no; podría estar equivocado al respecto, ya que no tengo documentación a mano, es decir, si no está obteniendo el BindingResult después de agregarlo al Modelo, intente utilizar un reenvío para confirmarlo).