Przekieruj do zewnętrznego adresu URL z akcji kontrolera w Spring MVC

118

Zauważyłem, że poniższy kod przekierowuje użytkownika na adres URL wewnątrz projektu,

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

podczas gdy poniższe przekierowanie zgodnie z przeznaczeniem, ale wymaga http: // lub 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;
    }

Chcę, aby przekierowanie zawsze przekierowywało do określonego adresu URL, niezależnie od tego, czy zawiera prawidłowy protokół, czy nie, i nie chcę przekierowywać do widoku. Jak mogę to zrobić?

Dzięki,

Jake
źródło

Odpowiedzi:

208

Możesz to zrobić na dwa sposoby.

Pierwszy:

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

Druga:

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public ModelAndView method() {
    return new ModelAndView("redirect:" + projectUrl);
}
Rinat Mukhamedgaliev
źródło
19
Jest to jeszcze prostsze, jeśli bezpośrednio zwracasz String, a nie ModelAndView.
daniel.eichten
24
Wydaje się, że w pierwszej metodzie należy ustawić kod powrotu na 302. W przeciwnym razie serwer zwróciłby odpowiedź z kodem 200 i nagłówkiem Location, co nie powoduje przekierowania w moim przypadku (Firefox 41.0).
Ivan Mushketyk
Czy możemy również dodać ciasteczka podczas przekierowania na zewnętrzny adres URL.
Srikar,
1
Pierwsza metoda wymaga@ResponseStatus(HttpStatus.FOUND)
lapkritinis
@Rinat Mukhamedgaliev W tym ModelAndView ("redirect:" + projectUrl); Stwierdzenie, jaki będzie klucz, zostanie przyjęty jako domyślny, jeśli dodana rzecz jest wartością?
JAVA,
56

Możesz użyć RedirectView. Skopiowano z JavaDoc :

Widok, który przekierowuje do bezwzględnego, względnego kontekstu lub bieżącego względnego adresu URL żądania

Przykład:

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

Możesz też użyć ResponseEntitynp

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

I oczywiście wróć, redirect:http://www.yahoo.comjak wspominali inni.

matsev
źródło
RedirectView był jedynym, który wydawał się działać dla mnie!
James111,
Mam dziwne zachowanie w widoku przekierowania, na webshpere otrzymuję: [kod] [27/04/17 13: 45: 55: 385 CDT] 00001303 webapp E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E : [Błąd serwletu] - [DispatcherPrincipal]: java.io.IOException: wzorzec niedozwolony w mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) pod adresem javax.servlet.http.HonseWervlet. sendRedirect (HttpServletResponseWrapper.java:145) [kod]
Carlos de Luna Saenz
49

Patrząc na rzeczywistą implementację UrlBasedViewResolver i RedirectView, przekierowanie zawsze będzie kontekstowe, jeśli cel przekierowania zaczyna się od /. Więc także wysłanie //yahoo.com/path/to/resource nie pomogłoby w uzyskaniu względnego przekierowania protokołu.

Aby osiągnąć to, co próbujesz, możesz zrobić coś takiego:

@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;
}
daniel.eichten
źródło
Ale w ten sposób przekierowanie jest GET, czy pozostaje POST? Jak przekierować jako POST?
Accollativo
Cóż, domyślnie zwraca to 302, co oznacza, że ​​powinien wydać GET na podany adres URL. W celu zachowania tej samej metody przekierowania należy również ustawić inny kod (307 od HTTP / 1.1). Ale jestem prawie pewien, że przeglądarki zablokują to, jeśli będzie to dotyczyło adresu bezwzględnego przy użyciu innej kombinacji host / port ze względu na problemy z bezpieczeństwem.
daniel.eichten
26

Innym sposobem jest użycie sendRedirectmetody:

@RequestMapping(
    value = "/",
    method = RequestMethod.GET)
public void redirectToTwitter(HttpServletResponse httpServletResponse) throws IOException {
    httpServletResponse.sendRedirect("https://twitter.com");
}
Ivan Mushketyk
źródło
22

Możesz to zrobić w dość zwięzły sposób, używając w ResponseEntityten sposób:

  @GetMapping
  ResponseEntity<Void> redirect() {
    return ResponseEntity.status(HttpStatus.FOUND)
        .location(URI.create("http://www.yahoo.com"))
        .build();
  }
k13i
źródło
1
To powinna być akceptowana odpowiedź. Niezwykle łatwy w konfiguracji i obsłudze.
cyberbit
9

U mnie działa dobrze:

@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);
}
Lord Nighton
źródło
Myślę, że ta metoda jest lepsza niż RedirectView, ponieważ działa również w listonoszach.
mehdi mohammadi
8

W przypadku zewnętrznego adresu URL musisz użyć „ http://www.yahoo.com ” jako adresu przekierowania.

Jest to wyjaśnione w redirect: prefix dokumentacji referencyjnej Spring.

redirect: / myapp / some / resource

przekieruje względem bieżącego kontekstu serwletu, podczas gdy nazwa taka jak

przekierowanie: http://myhost.com/some/arbitrary/path

przekieruje do bezwzględnego adresu URL

sreeprasad
źródło
3

Czy próbowałeś RedirectView, gdzie możesz podać parametr contextRelative?

Vijay Kukkala
źródło
Ten parametr jest przydatny w przypadku ścieżek, które zaczynają się (lub nie) od, /aby sprawdzić, czy powinien być względny w kontekście aplikacji internetowej. Żądanie przekierowania nadal będzie skierowane do tego samego hosta.
Sotirios Delimanolis
-2

Krótko mówiąc "redirect://yahoo.com", pożyczymy yahoo.com.

gdzie jak "redirect:yahoo.com"ci pożyczysz your-context/yahoo.comnp.localhost:8080/yahoo.com

hd1
źródło
oba rozwiązania mają to samo polecenie: "W skrócie" przekierowanie: yahoo.com "vs" gdzie jako "przekierowanie: yahoo.com" i działa tylko przekierowanie względnego adresu URL.
partizanos