Redirigir a una URL externa desde la acción del controlador en Spring MVC


118

He notado que el siguiente código redirige al usuario a una URL dentro del proyecto,

@RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm, 
                          BindingResult result, ModelMap model) 
{
    String redirectUrl = "yahoo.com";
    return "redirect:" + redirectUrl;
}

mientras que lo siguiente redirige correctamente según lo previsto, pero requiere http: // o https: //

@RequestMapping(method = RequestMethod.POST)
    public String processForm(HttpServletRequest request, LoginForm loginForm, 
                              BindingResult result, ModelMap model) 
    {
        String redirectUrl = "http://www.yahoo.com";
        return "redirect:" + redirectUrl;
    }

Quiero que la redirección siempre redirija a la URL especificada, ya sea que tenga un protocolo válido o no y no quiero redirigir a una vista. ¿Cómo puedo hacer eso?

Gracias,

Respuestas:


208

Puedes hacerlo de dos formas.

Primero:

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public void method(HttpServletResponse httpServletResponse) {
    httpServletResponse.setHeader("Location", projectUrl);
    httpServletResponse.setStatus(302);
}

Segundo:

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public ModelAndView method() {
    return new ModelAndView("redirect:" + projectUrl);
}

19
Es aún más simple si devuelve directamente un String en lugar de ModelAndView.
daniel.eichten

24
Parece que en el primer método debe establecer el código de retorno en 302. De lo contrario, un servidor devolvería una respuesta con el código 200 y el encabezado de ubicación que no causa redireccionamiento en mi caso (Firefox 41.0).
Ivan Mushketyk

¿Podemos también agregar cookies durante la redirección a una URL externa?
Srikar

1
Requiere primer método@ResponseStatus(HttpStatus.FOUND)
lapkritinis

@Rinat Mukhamedgaliev En este ModelAndView ("redireccionamiento:" + projectUrl); Enunciado ¿cuál sería la clave que se tomará por defecto, si el valor añadido es?
JAVA

56

Puede utilizar el RedirectView. Copiado de JavaDoc :

Vista que redirecciona a una URL relativa absoluta, relativa al contexto o relativa a la solicitud actual

Ejemplo:

@RequestMapping("/to-be-redirected")
public RedirectView localRedirect() {
    RedirectView redirectView = new RedirectView();
    redirectView.setUrl("http://www.yahoo.com");
    return redirectView;
}

También puede utilizar ResponseEntity, por ejemplo,

@RequestMapping("/to-be-redirected")
public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
    URI yahoo = new URI("http://www.yahoo.com");
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setLocation(yahoo);
    return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}

Y por supuesto, vuelve redirect:http://www.yahoo.comcomo han mencionado otros.


¡RedirectView fue el único que pareció funcionar para mí!
James111

Estoy teniendo un comportamiento extraño con Redirect View, en el sitio web obtengo: [código] [27/04/17 13: 45: 55: 385 CDT] 00001303 webapp E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E : [Error de servlet] - [DispatcherPrincipal]: java.io.IOException: patrón no permitido en mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) en javax.servlet.httServletp.Restt. sendRedirect (HttpServletResponseWrapper.java:145) [código]
Carlos de Luna Saenz

49

Al analizar la implementación real de UrlBasedViewResolver y RedirectView, la redirección siempre será contextRelative si su objetivo de redirección comienza con /. Por lo tanto, también enviar un //yahoo.com/path/to/resource no ayudaría a obtener una redirección relativa del protocolo.

Entonces, para lograr lo que está intentando, podría hacer algo como:

@RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm, 
                          BindingResult result, ModelMap model) 
{
    String redirectUrl = request.getScheme() + "://www.yahoo.com";
    return "redirect:" + redirectUrl;
}

¿Pero de esta manera la redirección es un GET o sigue siendo un POST? ¿Cómo redirecciono como POST?
Accollativo

Bueno, en realidad, por defecto, esto devuelve un 302, lo que significa que debería emitir un GET contra la URL proporcionada. Para que la redirección mantenga el mismo método, también debe establecer un código diferente (307 a partir de HTTP / 1.1). Pero estoy bastante seguro de que los navegadores bloquearán esto si va en contra de una dirección absoluta usando una combinación de puerto / host diferente debido a problemas de seguridad.
daniel.eichten

26

Otra forma de hacerlo es simplemente usar el sendRedirectmétodo:

@RequestMapping(
    value = "/",
    method = RequestMethod.GET)
public void redirectToTwitter(HttpServletResponse httpServletResponse) throws IOException {
    httpServletResponse.sendRedirect("https://twitter.com");
}

22

Puede hacer esto de una manera bastante concisa usando ResponseEntityasí:

  @GetMapping
  ResponseEntity<Void> redirect() {
    return ResponseEntity.status(HttpStatus.FOUND)
        .location(URI.create("http://www.yahoo.com"))
        .build();
  }

1
Esta debería ser la respuesta aceptada. Extremadamente fácil de configurar y utilizar.
cyberbit

9

Para mi funciona bien:

@RequestMapping (value = "/{id}", method = RequestMethod.GET)
public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
    URI uri = new URI("http://www.google.com");
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setLocation(uri);
    return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}

Creo que este método es mejor que RedirectView, ya que también funciona en el cartero.
mehdi mohammadi


3

¿Probó RedirectView donde puede proporcionar el parámetro contextRelative?


Ese parámetro es útil para las rutas que comienzan (o no) con /para verificar si debería ser relativo al contexto de la aplicación web. La solicitud de redireccionamiento seguirá siendo para el mismo host.
Sotirios Delimanolis

-2

En resumen "redirect://yahoo.com"te lo prestará yahoo.com.

donde como "redirect:yahoo.com"te prestará es your-context/yahoo.comdecir, por ejemplolocalhost:8080/yahoo.com


Ambas soluciones tienen el mismo comando: "En resumen" redireccionar: yahoo.com "vs" donde como "redireccionar: yahoo.com", y solo funciona la redirección de URL relativa.
partizanos
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.