Spring MVC @RestController and redirect

后端 未结 6 1081
闹比i
闹比i 2020-11-29 22:19

I have a REST endpoint implemented with Spring MVC @RestController. Sometime, depends on input parameters in my controller I need to send http redirect on client.

I

相关标签:
6条回答
  • 2020-11-29 22:27

    As the redirections are usually needed in a not-straightforward path, I think throwing an exception and handling it later is my favourite solution.

    Using a 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
        );
      }
    }
    

    The exception class in my case:

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

    And I trigger it like this:

    if (null == remoteUser)
      throw new NotLoggedInException("please log in", LOGIN_URL);
    
    0 讨论(0)
  • 2020-11-29 22:30

    To avoid any direct dependency on HttpServletRequest or HttpServletResponse I suggest a "pure Spring" implementation returning a ResponseEntity like this:

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

    If your method always returns a redirect, use ResponseEntity<Void>, otherwise whatever is returned normally as generic type.

    0 讨论(0)
  • 2020-11-29 22:31

    Add an HttpServletResponse parameter to your Handler Method then call response.sendRedirect("some-url");

    Something like:

    @RestController
    public class FooController {
    
      @RequestMapping("/foo")
      void handleFoo(HttpServletResponse response) throws IOException {
        response.sendRedirect("some-url");
      }
    
    }
    
    0 讨论(0)
  • 2020-11-29 22:32

    if you @RestController returns an String you can use something like this

    return "redirect:/other/controller/";
    

    and this kind of redirect is only for GET request, if you want to use other type of request use HttpServletResponse

    0 讨论(0)
  • 2020-11-29 22:40

    Came across this question and was surprised that no-one mentioned RedirectView. I have just tested it, and you can solve this in a clean 100% spring way with:

    @RestController
    public class FooController {
    
        @RequestMapping("/foo")
        public RedirectView handleFoo() {
            return new RedirectView("some-url");
        }
    }
    
    0 讨论(0)
  • 2020-11-29 22:45

    redirect means http code 302, which means Found in springMVC.

    Here is an util method, which could be placed in some kind of BaseController:

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

    But sometimes might want to return http code 301 instead, which means moved permanently.

    In that case, here is the util method:

    protected ResponseEntity movedPermanently(HttpServletResponse response, String url) { // 301, moved permanently,
        return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(HttpHeaders.LOCATION, url).build();
    }
    
    0 讨论(0)
提交回复
热议问题