我有一个用Spring MVC @RestController实现的REST端点。有时,取决于我控制器中的输入参数,我需要在客户端上发送http重定向。
Spring MVC @RestController是否可能,如果可以,请举个例子吗?
Answers:
将HttpServletResponse
参数添加到您的Handler方法,然后调用response.sendRedirect("some-url");
就像是:
@RestController
public class FooController {
@RequestMapping("/foo")
void handleFoo(HttpServletResponse response) throws IOException {
response.sendRedirect("some-url");
}
}
302
回报301
吗?
@RestController
使用a@Controller
和方法将aString
作为模板返回给您return "redirect:/mytemplate"
为了避免直接依赖,HttpServletRequest
或者HttpServletResponse
建议使用“纯Spring”实现,返回一个ResponseEntity,如下所示:
HttpHeaders headers = new HttpHeaders();
headers.setLocation(URI.create(newUrl));
return new ResponseEntity<>(headers, HttpStatus.MOVED_PERMANENTLY);
如果您的方法总是返回重定向,请使用ResponseEntity<Void>
,否则通常以泛型类型返回的任何内容。
return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(HttpHeaders.LOCATION, newUrl).build();
遇到了这个问题,令我惊讶的是没有人提到RedirectView。我刚刚对其进行了测试,您可以使用以下方法以干净的100%弹簧方式解决此问题:
@RestController
public class FooController {
@RequestMapping("/foo")
public RedirectView handleFoo() {
return new RedirectView("some-url");
}
}
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();
}
因为通常需要在非直截了当的路径中进行重定向,所以我认为抛出异常并在以后处理它是我最喜欢的解决方案。
使用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);
如果@RestController返回一个字符串,则可以使用类似以下的内容
return "redirect:/other/controller/";
并且这种重定向仅适用于GET请求,如果您想使用其他类型的请求,请使用HttpServletResponse
@Controller
但不适用于并添加注释@RestController
的专用版本。Spring Framework将转换返回值并将其自动写入http响应。 如果我们尝试访问该网址, 我们只会将字符串作为结果。@Controller
@ResponseBody
@RestController public class RedirectController { @RequestMapping("/redirect") public String redirect() { return "redirect:/other/controller/"; } }
curl localhost:8080/redirect
redirect:/other/controller/