Redirecionar para um URL externo da ação do controlador no Spring MVC


118

Percebi que o código a seguir está redirecionando o usuário para uma URL dentro do projeto,

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

enquanto o seguinte está redirecionando corretamente como pretendido, mas requer http: // ou 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;
    }

Quero que o redirecionamento sempre redirecione para a URL especificada, quer tenha um protocolo válido ou não, e não quero redirecionar para uma exibição. Como eu posso fazer isso?

Obrigado,

Respostas:


208

Você pode fazer isso de duas maneiras.

Primeiro:

@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
É ainda mais simples se você retornar diretamente uma String em vez de ModelAndView.
daniel.eichten

24
Parece que no primeiro método você deve definir o código de retorno para 302. Caso contrário, um servidor retornaria uma resposta com o código 200 e o cabeçalho Location que não causa redirecionamento no meu caso (Firefox 41.0).
Ivan Mushketyk,

Também podemos adicionar cookies durante o redirecionamento para URL externo.
Srikar,

1
O primeiro método requer@ResponseStatus(HttpStatus.FOUND)
lapkritinis

@Rinat Mukhamedgaliev Neste ModelAndView ("redirect:" + projectUrl); Instrução qual seria a chave será tomada como default, se o que agregou for valor?
JAVA

56

Você pode usar o RedirectView. Copiado do JavaDoc :

Visualização que redireciona para um URL absoluto, relativo ao contexto ou relativo à solicitação atual

Exemplo:

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

Você também pode usar um ResponseEntity, por exemplo

@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);
}

E, claro, volte redirect:http://www.yahoo.comconforme mencionado por outros.


O RedirectView foi o único que pareceu funcionar para mim!
James111

Estou tendo um comportamento estranho com a visualização de redirecionamento, no webshpere estou recebendo: [código] [27/04/17 13: 45: 55: 385 CDT] 00001303 webapp E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E : [Erro de servlet] - [DispatcherPrincipal]: java.io.IOException: padrão não permitido em mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) em javax.servlet.http.HttpSrapervletResponlet. sendRedirect (HttpServletResponseWrapper.java:145) [código]
Carlos de Luna Saenz

49

Olhando para a implementação real de UrlBasedViewResolver e RedirectView, o redirecionamento sempre será contextRelative se seu destino de redirecionamento começar com /. Portanto, o envio de //yahoo.com/path/to/resource não ajudaria a obter um redirecionamento relativo de protocolo.

Então, para alcançar o que você está tentando, você pode fazer 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;
}

Mas, desta forma, o redirecionamento é um GET ou permanece um POST? Como faço para redirecionar como POST?
Accollativo

Bem, na verdade, por padrão, isso está retornando um 302, o que significa que deve emitir um GET contra o url fornecido. Para o redirecionamento mantendo o mesmo método, você também deve definir um código diferente (307 a partir de HTTP / 1.1). Mas tenho quase certeza de que os navegadores irão bloquear isso se for contra um endereço absoluto usando uma combinação diferente de host / porta devido a problemas de segurança.
daniel.eichten

26

Outra maneira de fazer isso é usar o sendRedirectmétodo:

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

22

Você pode fazer isso de forma bastante concisa usando ResponseEntityassim:

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

1
Esta deve ser a resposta aceita. Extremamente fácil de configurar e usar.
cyberbit

9

Para mim funciona bem:

@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);
}

Acho que esse método é melhor que o RedirectView, pois funciona no carteiro também.
mehdi mohammadi


3

Você tentou RedirectView, onde pode fornecer o parâmetro contextRelative?


Esse parâmetro é útil para caminhos que começam (ou não) com /para verificar se ele deve ser relativo ao contexto do webapp. A solicitação de redirecionamento ainda será para o mesmo host.
Sotirios Delimanolis

-2

Em suma, "redirect://yahoo.com"vou emprestar para você yahoo.com.

onde "redirect:yahoo.com"vai lhe emprestar, your-context/yahoo.comou seja, para ex-localhost:8080/yahoo.com


ambas as soluções têm o mesmo comando: "Resumindo" redirect: yahoo.com "vs" onde como "redirect: yahoo.com", e apenas o redirecionamento de url relativo está funcionando.
partizanos
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.