2011-12-21 13 views
18

¿Hay alguna manera de reenviar una solicitud a otro Controlador mientras se le agregan algunos datos de parámetros? Traté de agregar al ModelMap, pero no parece que se mantenga. Estoy haciendo algo como:¿Avanzar con los parámetros añadidos?

return "forward:/my-other-controller"; 

única otra forma que se me ocurre es poner los parámetros de la sesión y luego hacerlas explotar fuera en el controlador de destino.

Respuesta

39

La forma más sencilla es agregar los datos a la solicitud. Como se trata de un reenvío, la misma solicitud se pasa a diferentes controladores dentro del servidor.

Como ejemplo, vamos a empezar con una simple configuración de dos controladores, uno enviado hacia el otro:

@Controller 
public class TestController { 
    @RequestMapping(value="/test") 
    public String showTestPage() { 
     return "forward:/test2"; 
    } 
} 

@Controller 
public class TestController2 { 
    @RequestMapping(value="/test2") 
    public String showTestPage() { 
     return "testPageView"; 
    } 
} 

Primera forma de añadir los datos son para establecerlo como atributos de la petición. Los nuevos controladores van a tener este aspecto (Un):

@Controller 
public class TestController { 
    @RequestMapping(value="/test") 
    public String showTestPage(HttpServletRequest request) { 
     request.setAttribute("param1", "foo"); 
     request.setAttribute("param2", "bar"); 
     return "forward:/test2"; 
    } 
} 

@Controller 
public class TestController2 { 
    @RequestMapping(value="/test2") 
    public String showTestPage(HttpServletRequest request) { 
     String param1 = (String) request.getAttribute("param1"); 
     String param2 = (String) request.getAttribute("param2"); 
     return "testPageView"; 
    } 
} 

Dado que el nombre de la vista en el forward prefix is basically an URL, también puede tener las versiones siguientes (atributo cambiado a parámetros) (B):

@Controller 
public class TestController { 
    @RequestMapping(value="/test") 
    public String showTestPage() { 
     return "forward:/test2?param1=foo&param2=bar"; 
    } 
} 

@Controller 
public class TestController2 { 
    @RequestMapping(value="/test2") 
    public String showTestPage(HttpServletRequest request) { 
     String param1 = request.getParameter("param1"); 
     String param2 = request.getParameter("param2"); 
     return "testPageView"; 
    } 
} 

también puede simplificar aún más el segundo controlador mediante el uso de anotaciones en su lugar:

@Controller 
public class TestController2 { 
    @RequestMapping(value="/test2") 
    public String showTestPage(@RequestParam String param1, @RequestParam String param2) { 
     return "testPageView"; 
    } 
} 

Y sólo por el gusto de hacerlo, y para mostrar comportamiento de enlace de la primavera en la acción, que podría hacer que sea aún así (C):

@Controller 
public class TestController { 
    @RequestMapping(value="/test") 
    public String showTestPage() { 
     return "forward:/test2?param1=foo&param2=bar"; 
    } 
} 

@Controller 
public class TestController2 { 
    @RequestMapping(value="/test2") 
    public String showTestPage(@ModelAttribute DummyBinder params) { 
     String param1 = params.getParam1(); 
     String param2 = params.getParam2(); 
     return "testPageView"; 
    } 
} 

class DummyBinder { 
    private String param1; 
    private String param2; 

    public String getParam1() { 
     return param1; 
    } 

    public void setParam1(String param1) { 
     this.param1 = param1; 
    } 

    public String getParam2() { 
     return param2; 
    } 

    public void setParam2(String param2) { 
     this.param2 = param2; 
    } 
} 

me iría personalmente con la solución A para muchos parámetros y la solución B para algunos. La solución C tiene una especie de "¿eh ...?" efecto, así que lo evitaría (también funciona con los parámetros agregados a la URL, por lo que algunos de ellos o usted obtiene una URL desordenada).

Agregar los datos en la sesión también funcionaría fuera de curso, pero extendería la vida útil de los datos innecesariamente, por lo que el mejor lugar es agregarlo a la solicitud durante la transición al segundo controlador.

+1

¡Gracias por la gran respuesta! Esto llega al corazón de mi confusión. Hay "atributos" y "parámetros" por todas partes y nunca parece entender cuál es cuál. Mi solicitud POST tiene datos binarios en el cuerpo, por lo que no puedo usar eso para los "parámetros" codificados en la URL. Entonces, ¿qué hace request.setAttribute() en realidad? ¿Son estos solo pares arbitrarios de clave/valor que están en el objeto HttpServletRequest, O están almacenados como parámetros HTTP reales, como una cadena de consulta, etc.? ¿Y cuál es la diferencia entre request.setAttribute y request.setParameter? –

+2

@Tony R: los parámetros son los que su usuario envía al enviar en un GET/POST. Se trata principalmente de datos de solo lectura (no hay request.setParameter; el servidor crea el objeto de solicitud con los parámetros internos para que pueda obtener). Los atributos son datos colocados en un cierto alcance en su servidor. Utiliza request.setAttribute para colocar datos en "ámbito de solicitud" (por ejemplo, también puede tener alcance de sesión o alcance de aplicación). Puede agregar atributos, obtenerlos o eliminarlos. Aquí hay una explicación simple: http://www.xyzws.com/Servletfaq/what-is-the-difference-between-the-request-attribute-and-request-parameter/1 – Bogdan

+1

Muchas gracias por la explicación. No me di cuenta de que los parámetros son de solo lectura, lo que realmente tiene mucho sentido. Ahora la respuesta parece trivial ... De hecho, me pregunto por qué tomó tanto tiempo obtener esta respuesta, ya que las otras ahora parecen estar "equivocadas" **. –

0

Considere el reenvío al igual que el redireccionamiento, pero sin la necesidad de un contexto y host en este sentido (el servidor maneja el reenvío, mientras que el redireccionamiento le indica al navegador del usuario que solicite un URL diferente).

Así que, sí, use la sesión, las cookies o publíquelos o consiga los parámetros.

+0

La solicitud ya tiene sus propios parámetros ... Quiero que ellos también lo hagan. Pero también me gustaría el Modelo y tal vez hay otras formas de enviar datos. –

+0

¿Ha intentado agregar ModelMap a su controlador y agregar sus nuevos valores a los que usa el controlador reenviado? – Steven

+0

Sí, lo intenté y no se encontró el parámetro –

0

¿Ha considerado los filtros? Puede crear un filtro utilizando el proxy de filtro de delegación que le dará acceso a los parámetros de solicitud, así como a los beans de primavera.

+0

¿Puede elaborarme o señalarme un ejemplo? No veo cómo encaja eso. –

+0

@Tony. Se me dio la opción de redireccionar la solicitud e intentar cambiar los parámetros usando un filtro. Si desea usar reenvío, querrá usar atributos de sesión. –

+0

No puedo ver cómo funcionaría eso. Por lo que Tony ha dicho hasta ahora, dudo que haya algo en los atributos de solicitud que necesite. – Steven

0

que he encontrado this post, que utiliza un HttpRequestWrapper:

Primero:
Definir el HttpRequestWrapper y anulan los métodos getParameter, getParameterMap, getParameterNames y getParameterValues como en el post.

Segundo:
Transmita por RequestDispatcher a su URL, utilizando la envuelta solicitud en los parámetros del método:

request.getRequestDispatcher("myForwardUrl").forward(new MyRequestWrapper(request), response); 

He intentado esto para borrado de parámetros (que es aún más ¡Difícil!) ¡Y funciona!