เปลี่ยนเส้นทางไปยัง URL ภายนอกจากการดำเนินการของคอนโทรลเลอร์ใน Spring MVC


118

ฉันสังเกตเห็นว่ารหัสต่อไปนี้กำลังเปลี่ยนเส้นทางผู้ใช้ไปยัง URL ภายในโครงการ

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

ในขณะที่สิ่งต่อไปนี้กำลังเปลี่ยนเส้นทางอย่างถูกต้องตามที่ตั้งใจไว้ แต่ต้องใช้ http: // หรือ 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;
    }

ฉันต้องการให้การเปลี่ยนเส้นทางเปลี่ยนเส้นทางไปยัง URL ที่ระบุเสมอไม่ว่าจะมีโปรโตคอลที่ถูกต้องอยู่ในนั้นหรือไม่ก็ตามและไม่ต้องการเปลี่ยนเส้นทางไปยังข้อมูลพร็อพเพอร์ตี้ ฉันจะทำเช่นนั้นได้อย่างไร?

ขอบคุณ

คำตอบ:


208

คุณสามารถทำได้ด้วยสองวิธี

ครั้งแรก:

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

ประการที่สอง:

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

19
มันง่ายกว่าถ้าคุณส่งคืน String โดยตรงแทนที่จะเป็น ModelAndView
daniel.eichten

24
ดูเหมือนว่าในวิธีแรกคุณควรตั้งรหัสส่งคืนเป็น 302 มิฉะนั้นเซิร์ฟเวอร์จะส่งคืนการตอบสนองด้วยรหัส 200 และส่วนหัวตำแหน่งซึ่งไม่ทำให้เกิดการเปลี่ยนเส้นทางในกรณีของฉัน (Firefox 41.0)
Ivan Mushketyk

เราสามารถเพิ่มคุกกี้ระหว่างการเปลี่ยนเส้นทางไปยัง URL ภายนอกได้หรือไม่
Srikar

1
วิธีแรกต้องใช้@ResponseStatus(HttpStatus.FOUND)
lapkritinis

@Rinat Mukhamedgaliev ใน ModelAndView นี้ ("redirect:" + projectUrl); คำแถลงว่าคีย์จะถูกยึดเป็นค่าเริ่มต้นหากสิ่งที่เพิ่มคือมูลค่า?
JAVA

57

คุณสามารถใช้ไฟล์RedirectView. คัดลอกจากJavaDoc :

ดูว่าเปลี่ยนเส้นทางไปยัง URL สัมพัทธ์ตามบริบทหรือคำขอปัจจุบันแบบสัมบูรณ์

ตัวอย่าง:

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

คุณยังสามารถใช้ a ResponseEntityเช่น

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

และแน่นอนกลับมาredirect:http://www.yahoo.comตามที่คนอื่นกล่าวถึง


RedirectView เป็นเครื่องเดียวที่ดูเหมือนจะใช้ได้กับฉัน!
James111

ฉันมีพฤติกรรมที่ไม่ดีพร้อมกับ Redirect View บน webshpere ฉันได้รับ: [code] [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: ไม่อนุญาตให้ใช้รูปแบบที่ mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) ที่ javax.servlet.http.HttpServletRes sendRedirect (HttpServletResponseWrapper.java:145) [code]
Carlos de Luna Saenz

49

เมื่อพิจารณาถึงการนำUrlBasedViewResolverและRedirectViewไปใช้งานจริงการเปลี่ยนเส้นทางจะเป็น contextRelative เสมอหากเป้าหมายการเปลี่ยนเส้นทางของคุณเริ่มต้นด้วย / ดังนั้นการส่ง //yahoo.com/path/to/resource จะไม่ช่วยในการเปลี่ยนเส้นทางแบบสัมพัทธ์ของโปรโตคอล

ดังนั้นเพื่อให้บรรลุสิ่งที่คุณพยายามคุณสามารถทำสิ่งต่างๆเช่น:

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

แต่ด้วยวิธีนี้การเปลี่ยนเส้นทางเป็น GET หรือยังคงเป็น POST? ฉันจะเปลี่ยนเส้นทางเป็น POST ได้อย่างไร
Accollativo

ตามค่าเริ่มต้นนี่เป็นการส่งคืน 302 ซึ่งหมายความว่าควรออก GET กับ url ที่ให้มา สำหรับการเปลี่ยนเส้นทางโดยใช้วิธีการเดียวกันคุณควรตั้งรหัสอื่น (307 เป็น HTTP / 1.1) แต่ฉันค่อนข้างแน่ใจว่าเบราว์เซอร์จะบล็อกสิ่งนี้หากมันขัดกับที่อยู่ที่แน่นอนโดยใช้โฮสต์ / พอร์ตที่แตกต่างกันเนื่องจากปัญหาด้านความปลอดภัย
daniel.eichten

26

อีกวิธีในการทำคือใช้sendRedirectวิธีการ:

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

23

คุณสามารถทำได้อย่างกระชับโดยใช้ResponseEntityสิ่งนี้:

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

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ง่ายมากที่จะติดตั้งและใช้งาน.
cyberbit

9

สำหรับฉันทำงานได้ดี:

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

ฉันคิดว่าวิธีนี้ดีกว่า RedirectView เพราะมันทำงานในบุรุษไปรษณีย์ด้วย
mehdi mohammadi

8

สำหรับ URL ภายนอกคุณต้องใช้ " http://www.yahoo.com " เป็น URL เปลี่ยนเส้นทาง

สิ่งนี้อธิบายไว้ในredirect: คำนำหน้าของเอกสารอ้างอิง Spring

เปลี่ยนเส้นทาง: / myapp / บาง / ทรัพยากร

จะเปลี่ยนเส้นทางโดยสัมพันธ์กับบริบท Servlet ปัจจุบันในขณะที่ชื่อเช่น

เปลี่ยนเส้นทาง: http://myhost.com/some/arbitrary/path

จะเปลี่ยนเส้นทางไปยัง URL ที่สมบูรณ์


3

คุณลองRedirectViewที่ให้พารามิเตอร์ contextRelative หรือไม่


พารามิเตอร์นั้นมีประโยชน์สำหรับเส้นทางที่เริ่มต้น (หรือไม่) /เพื่อตรวจสอบว่าควรสัมพันธ์กับบริบทของเว็บแอปหรือไม่ คำขอเปลี่ยนเส้นทางจะยังคงเป็นของโฮสต์เดิม
Sotirios Delimanolis

-2

ในระยะสั้นจะให้ยืมคุณ"redirect://yahoo.com"yahoo.com

ที่"redirect:yahoo.com"จะให้คุณยืมyour-context/yahoo.comเช่นอดีต -localhost:8080/yahoo.com


โซลูชันทั้งสองมีคำสั่งเดียวกัน: "ในระยะสั้น" redirect: yahoo.com "vs" โดยที่เป็น "redirect: yahoo.com" และมีเพียงการเปลี่ยนเส้นทาง url สัมพัทธ์เท่านั้นที่ทำงานได้
partizanos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.