Spring MVC @RestController并重定向


76

我有一个用Spring MVC @RestController实现的REST端点。有时,取决于我控制器中的输入参数,我需要在客户端上发送http重定向。

Spring MVC @RestController是否可能,如果可以,请举个例子吗?



2
您的链接信息不适用于@RestController课程,因为它包含@ResponseBody。您的“重定向:”字符串不会被解释为视图。

Answers:


119

HttpServletResponse参数添加到您的Handler方法,然后调用response.sendRedirect("some-url");

就像是:

@RestController
public class FooController {

  @RequestMapping("/foo")
  void handleFoo(HttpServletResponse response) throws IOException {
    response.sendRedirect("some-url");
  }

}

3
可悲的是,这似乎是唯一的解决方案。我也希望没有HttpServletResponse参数有更好的方法。

2
@MajidLaissi-实际上,这是非常可悲的。在大多数情况下,有可能完全将Spring MVC控制器完全抽象为完全不依赖HTTP作为传输协议的任何依赖,但是遗憾的是在这里是不可能的。
Jules

我喜欢这个解决方案,也喜欢@Arne Burmeister的解决方案,但是它们都不解决我的浏览器问题,因为这里
Mahesh

这就是302回报301吗?
特朗普2020-正义将于

而不是@RestController使用a@Controller和方法将aString作为模板返回给您return "redirect:/mytemplate"
Phill Alexakis 20-4-11

58

为了避免直接依赖,HttpServletRequest或者HttpServletResponse建议使用“纯Spring”实现,返回一个ResponseEntity,如下所示:

HttpHeaders headers = new HttpHeaders();
headers.setLocation(URI.create(newUrl));
return new ResponseEntity<>(headers, HttpStatus.MOVED_PERMANENTLY);

如果您的方法总是返回重定向,请使用ResponseEntity<Void>,否则通常以泛型类型返回的任何内容。


12
或成一行return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(HttpHeaders.LOCATION, newUrl).build();
JohannesFlügel'Jan

1
在这种情况下,newUrl是否必须是完全限定的URL?如果是这样,则在重定向到应用程序中的另一个URL时,此解决方案充其量是笨拙的,因为您必须构建整个URL。使用HttpServletResponse允许您发送相对于servlet容器根目录的重定向。
matt forsythe

如果您使用摇摇欲坠的客户端生成代码,它就像一个魅力;-)
Jimmy Pannier19年

我正在尝试在其中添加一个自定义标头以及“位置”,但是它不起作用吗?@Arne
Arpit Suthar

19

遇到了这个问题,令我惊讶的是没有人提到RedirectView。我刚刚对其进行了测试,您可以使用以下方法以干净的100%弹簧方式解决此问题:

@RestController
public class FooController {

    @RequestMapping("/foo")
    public RedirectView handleFoo() {
        return new RedirectView("some-url");
    }
}

任何想法如何使用上下文路径设置url?
Bahij.Mik

@ Bahij.Mik我假设您正在询问servlet上下文路径-以下内容告诉我可以自动连接servlet上下文并从其链接中
DhatGuy

1

redirect表示http代码302,这Found在springMVC中表示。

这是一个util方法,可以放在某种形式的方法中BaseController

protected ResponseEntity found(HttpServletResponse response, String url) throws IOException { // 302, found, redirect,
    response.sendRedirect(url);
    return null;
}

但有时可能想返回http代码301,这意味着moved permanently

在这种情况下,这是util方法:

protected ResponseEntity movedPermanently(HttpServletResponse response, String url) { // 301, moved permanently,
    return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(HttpHeaders.LOCATION, url).build();
}

0

因为通常需要在非直截了当的路径中进行重定向,所以我认为抛出异常并在以后处理它是我最喜欢的解决方案。

使用ControllerAdvice

@ControllerAdvice
public class RestResponseEntityExceptionHandler
    extends ResponseEntityExceptionHandler {

  @ExceptionHandler(value = {
      NotLoggedInException.class
  })
  protected ResponseEntity<Object> handleNotLoggedIn(
      final NotLoggedInException ex, final WebRequest request
  ) {
    final String bodyOfResponse = ex.getMessage();

    final HttpHeaders headers = new HttpHeaders();
    headers.add("Location", ex.getRedirectUri());
    return handleExceptionInternal(
        ex, bodyOfResponse,
        headers, HttpStatus.FOUND, request
    );
  }
}

在我的情况下的异常类:

@Getter
public class NotLoggedInException extends RuntimeException {

  private static final long serialVersionUID = -4900004519786666447L;

  String redirectUri;

  public NotLoggedInException(final String message, final String uri) {
    super(message);
    redirectUri = uri;
  }
}

我这样触发它:

if (null == remoteUser)
  throw new NotLoggedInException("please log in", LOGIN_URL);

-12

如果@RestController返回一个字符串,则可以使用类似以下的内容

return "redirect:/other/controller/";

并且这种重定向仅适用于GET请求,如果您想使用其他类型的请求,请使用HttpServletResponse


14
它仅适用于,@Controller但不适用于并添加注释@RestController的专用版本。Spring Framework将转换返回值并将其自动写入http响应。 如果我们尝试访问该网址, 我们只会将字符串作为结果。@Controller@ResponseBody@RestController public class RedirectController { @RequestMapping("/redirect") public String redirect() { return "redirect:/other/controller/"; } }curl localhost:8080/redirectredirect:/other/controller/
Anton Balaniuc '16

3
安东·巴拉纽克(Anton Balaniuc)是正确的,而阅读整个答案仍然不正确。在RestController中,它将仅返回字符串“ redirect:/ other / controller”,而不进行重定向
S. Jacob Powell
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.