El controlador Spring-MVC redirige a & # 8220; anterior & # 8221; ¿página?
-
03-07-2019 - |
Pregunta
Digamos que tengo un formulario para editar las propiedades de un Pony, y en mi aplicación web hay varios lugares donde puedes elegir editar un Pony. Por ejemplo, en una lista de ponis podría haber una " editar " enlace al lado de cada Pony, y cuando el usuario está viendo un Pony, también puede haber una " editar " enlace en esa vista.
Cuando un usuario hace clic en " enviar " después de editar un Pony, me gustaría devolver al usuario a la página que tenía cuando hizo clic en " editar " enlace.
¿Cómo escribo mi controlador para redirigir al usuario a donde comenzaron? Ciertamente, puedo hacer esto pasando un parámetro al controlador, pero eso parece un poco tonto. ¿Estoy pensando en todo esto mal o es más o menos lo que tendré que hacer?
Solución
Una opción, por supuesto, sería abrir el formulario de edición en una nueva ventana, por lo que todo lo que el usuario tiene que hacer es cerrarlo y volver a estar donde estaban.
Hay algunos lugares en mi aplicación actual en los que necesito hacer algo complicado, luego pasar al usuario a un formulario y luego hacer que vuelvan al punto de inicio. En esos casos, almaceno el punto de inicio en la sesión antes de pasarlos. Probablemente eso sea excesivo por lo que estás haciendo.
Otras opciones: 1) puede almacenar el " Referer " Encabezar y usar eso, pero eso puede no ser confiable; no todos los navegadores establecen ese encabezado. 2) podría tener javascript en la página de confirmación después del envío del formulario que llama a " history.go (-2)
" ;.
Otros consejos
Aquí se explica cómo hacerlo, muchachos (tenga en cuenta que esta es la sintaxis de RESTful Spring 3 MVC, pero funcionará en los controladores Spring más antiguos):
@RequestMapping(value = "/rate", method = RequestMethod.POST)
public String rateHandler(HttpServletRequest request) {
//your controller code
String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}
Mi respuesta es similar a la de Sam Brodkins (también lo recomendé). Pero teniendo en cuenta que el " Referente " el valor puede no estar disponible. Hice esta función para usarla en mis controladores
/**
* Returns the viewName to return for coming back to the sender url
*
* @param request Instance of {@link HttpServletRequest} or use an injected instance
* @return Optional with the view name. Recomended to use an alternativa url with
* {@link Optional#orElse(java.lang.Object)}
*/
protected Optional<String> getPreviousPageByRequest(HttpServletRequest request)
{
return Optional.ofNullable(request.getHeader("Referer")).map(requestUrl -> "redirect:" + requestUrl);
}
Entonces, en la función de llamador de tu controlador, deberías devolver algo como esto:
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody
String testRedirection(HttpServletRequest request)
{
//Logic....
//Returns to the sender url
return getPreviousPageByRequest(request).orElse("/"); //else go to home page
}
Sí, creo que la idea de Jacob para el formulario en una nueva ventana puede ser una buena opción. O en un div oculto. Como un diálogo de dojo. http://dojocampus.org/explorer/#Dijit_Dialog_Basic
otra opción sería diseñar tus URL para que revelen el contexto de lo que estás haciendo y, por convención, te permitiría " saber " donde estaba el inicio de una operación.
Por ejemplo, podría tener urls así
site/section1/pony/edit
site/section1/pony/delete
site/somewhere/else/entirely/pony/edit
site/somewhere/else/entirely/pony/delete
ambas direcciones URL permiten editar y eliminar pony. Para volver al inicio para ambos, simplemente subes " arriba " 2 carpetas. Esto se puede hacer a través de una función javascript que mira la url actual, y solo sube 2 carpetas, o puede descifrarlo en el lado del servidor 2, y hacer una redirección como esa también.
También puede realizar un seguimiento del ModelAndView (o solo la vista) que se presentó por última vez al usuario con un interceptor. Este ejemplo solo hace un seguimiento del último modelo y la vista, pero puede usar una lista para navegar más niveles.
package com.sample;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LastModelAndViewInterceptor extends HandlerInterceptorAdapter {
public static final String LAST_MODEL_VIEW_ATTRIBUTE = LastModelAndViewInterceptor.class.getName() + ".lastModelAndView";
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
request.getSession(true).setAttribute(LAST_MODEL_VIEW_ATTRIBUTE, modelAndView);
super.postHandle(request, response, handler, modelAndView);
}
}
Con la configuración XML de Spring:
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<bean class="com.sample.LastModelAndViewInterceptor"/>
</property>
</bean>
Y luego use el siguiente código para volver a esa vista en un controlador:
ModelAndView mv = (ModelAndView)request.getSession().getAttribute(LastModelAndViewInterceptor.LAST_MODEL_VIEW_ATTRIBUTE);
return mv;