Перенаправление на внешний 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 и заголовком Location, который в моем случае не вызывает перенаправления (Firefox 41.0).
Иван Мушкетик
Можем ли мы также добавить файлы cookie во время перенаправления на внешний URL.
Srikar 09
1
Первый метод требует@ResponseStatus(HttpStatus.FOUND)
лапкритинис 09
@ Ринат Мухамедгалиев В этом ModelAndView ("перенаправление:" + 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;
}

Вы также можете использовать 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чем говорили другие.

matsev
источник
RedirectView был единственным, который, казалось, работал у меня!
James111
У меня странное поведение с представлением перенаправления, на webshpere я получаю: [код] [27.04.17 13:45: 55: 385 CDT] 00001303 webapp E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E : [Ошибка в сервлете] - [DispatcherPrincipal]: java.io.IOException: шаблон не разрешен в mx.isban.security.components.SecOutputFilter $ WrapperRsSecured.sendRedirect (SecOutputFilter.java:234) в javax.servlet.httvrapper.Http sendRedirect (HttpServletResponseWrapper.java:145) [code]
Карлос де Луна Саенс,
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;
}
daniel.eichten
источник
Но в этом случае перенаправление является GET или остается POST? Как мне перенаправить как POST?
Accollativo 01
Ну, на самом деле по умолчанию это возвращает 302, что означает, что он должен выдать GET для предоставленного URL-адреса. Для перенаправления с сохранением того же метода вы также должны установить другой код (307 с HTTP / 1.1). Но я почти уверен, что браузеры заблокируют это, если это противоречит абсолютному адресу с использованием другой комбинации хоста / порта из-за проблем с безопасностью.
daniel.eichten 01
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();
  }
k13i
источник
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, так как он работает и в почтальоне.
Мехди Мохаммади
8

Для внешнего URL-адреса вы должны использовать « http://www.yahoo.com » в качестве URL-адреса перенаправления.

Это объясняется в префиксе redirect: справочной документации Spring.

переадресовать: / MyApp / некоторые / ресурс

будет перенаправлять относительно текущего контекста сервлета, в то время как имя, такое как

перенаправление: http://myhost.com/some/arbitrary/path

перенаправит на абсолютный URL

sreeprasad
источник
3

Вы пробовали RedirectView, где можно указать параметр contextRelative?

Виджай Куккала
источник
Этот параметр полезен для путей, которые начинаются (или не начинаются), /чтобы проверить, должен ли он относиться к контексту веб-приложения. Запрос на перенаправление по-прежнему будет для того же хоста.
Сотириос Делиманолис
-2

Короче "redirect://yahoo.com"одолжу тебеyahoo.com .

где как "redirect:yahoo.com"одолжит то your-context/yahoo.comесть за экс-localhost:8080/yahoo.com

hd1
источник
в обоих решениях используется одна и та же команда: «Короче» redirect: yahoo.com «vs», где «redirect: yahoo.com», и работает только относительное перенаправление URL.
partizanos