Alihkan ke URL eksternal dari tindakan pengontrol di Spring MVC

118

Saya telah memperhatikan kode berikut mengarahkan Pengguna ke URL di dalam proyek,

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

sedangkan, berikut ini mengalihkan dengan benar seperti yang diinginkan, tetapi membutuhkan http: // atau 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;
    }

Saya ingin pengalihan untuk selalu mengarahkan ke URL yang ditentukan, apakah memiliki protokol yang valid di dalamnya atau tidak dan tidak ingin mengalihkan ke tampilan. Bagaimana saya bisa melakukan itu?

Terima kasih,

Jake
sumber

Jawaban:

208

Anda bisa melakukannya dengan dua cara.

Pertama:

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

Kedua:

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public ModelAndView method() {
    return new ModelAndView("redirect:" + projectUrl);
}
Rinat Mukhamedgaliev
sumber
19
Bahkan lebih sederhana jika Anda secara langsung mengembalikan String daripada ModelAndView.
daniel.eichten
24
Tampaknya dalam metode pertama Anda harus menyetel kode pengembalian ke 302. Jika tidak, server akan mengembalikan respons dengan kode 200 dan header Lokasi yang tidak menyebabkan pengalihan dalam kasus saya (Firefox 41.0).
Ivan Mushketyk
Bisakah kita juga menambahkan cookie saat mengarahkan ke URL Eksternal.
Srikar
1
Metode pertama membutuhkan@ResponseStatus(HttpStatus.FOUND)
lapkritinis
@Rinat Mukhamedgaliev Dalam ModelAndView ini ("redirect:" + projectUrl); Pernyataan apa yang akan menjadi kunci akan diambil sebagai default, jika yang ditambahkan adalah nilai?
JAVA
56

Anda dapat menggunakan RedirectView. Disalin dari JavaDoc :

Tampilan yang mengalihkan ke URL relatif, relatif konteks, atau permintaan saat ini

Contoh:

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

Anda juga dapat menggunakan ResponseEntity, mis

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

Dan tentu saja, kembali redirect:http://www.yahoo.comseperti yang disebutkan oleh orang lain.

matsev
sumber
RedirectView adalah satu-satunya yang tampaknya berhasil untuk saya!
Yakobus111
Saya mengalami perilaku stange dengan Tampilan Pengalihan, di webshpere saya mendapatkan: [kode] [27/04/17 13: 45: 55: 385 CDT] 00001303 aplikasi web E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E : [Error de servlet] - [DispatcherPrincipal]: java.io.IOException: pola tidak diizinkan di mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) di javax.servlet.http.HttpServletResponslet.http.HttpServletResponslet. sendRedirect (HttpServletResponseWrapper.java:145) [kode]
Carlos de Luna Saenz
49

Melihat implementasi sebenarnya dari UrlBasedViewResolver dan RedirectView , pengalihan akan selalu menjadi contextRelative jika target pengalihan Anda dimulai dengan /. Jadi, juga mengirimkan //yahoo.com/path/to/resource tidak akan membantu mendapatkan pengalihan relatif protokol.

Jadi untuk mencapai apa yang Anda coba, Anda dapat melakukan sesuatu seperti:

@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
sumber
Tetapi dengan cara ini pengalihannya adalah GET atau tetap menjadi POST? Bagaimana cara mengalihkan sebagai POST?
Accollativo
Sebenarnya secara default ini mengembalikan 302 yang berarti harus mengeluarkan GET terhadap url yang disediakan. Untuk pengalihan dengan tetap menggunakan metode yang sama, Anda juga harus menyetel kode yang berbeda (307 pada HTTP / 1.1). Tetapi saya cukup yakin bahwa browser akan memblokir ini jika itu bertentangan dengan alamat absolut menggunakan kombinasi host / port yang berbeda karena masalah keamanan.
daniel.eichten
26

Cara lain untuk melakukannya adalah dengan menggunakan sendRedirectmetode ini:

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

Anda dapat melakukan ini dengan cara yang cukup ringkas menggunakan ResponseEntityseperti ini:

  @GetMapping
  ResponseEntity<Void> redirect() {
    return ResponseEntity.status(HttpStatus.FOUND)
        .location(URI.create("http://www.yahoo.com"))
        .build();
  }
k13i
sumber
1
Ini harus menjadi jawaban yang diterima. Sangat mudah diatur dan digunakan.
cyberbit
9

Bagi saya bekerja dengan baik:

@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
sumber
Saya pikir metode ini lebih baik daripada RedirectView karena bekerja di tukang pos juga.
mehdi mohammadi
3

Apakah Anda mencoba RedirectView di mana Anda bisa memberikan parameter contextRelative?

Vijay Kukkala
sumber
Parameter itu berguna untuk jalur yang dimulai (atau tidak) dengan /untuk memeriksa apakah harus relatif terhadap konteks webapp. Permintaan pengalihan akan tetap untuk host yang sama.
Sotirios Delimanolis
-2

Singkatnya "redirect://yahoo.com"akan meminjamkan Andayahoo.com .

dimana "redirect:yahoo.com"akan meminjamkanmu your-context/yahoo.comyaitu untuk mantanlocalhost:8080/yahoo.com

hd1
sumber
kedua solusi memiliki perintah yang sama: "Singkatnya" redirect: yahoo.com "vs" sedangkan "redirect: yahoo.com", dan hanya pengalihan url relatif yang bekerja.
partizanos