2016-09-02 2 views
3

스프링 부트를 사용하여 HandlerInterceptor로드 균형 조정 (일종의)을 구현하고 있습니다.스프링 부트 HandlerInterceptor loadbalancing

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
    String uri = request.getRequestURI(); 
    if (shouldUseServer1(uri)) { 
     response.sendRedirect(server1Uri); 
    } else { 
     response.sendRedirect(server2Uri); 
    } 
} 

URL을 기반으로하는 서비스는 하나의 서비스 또는 다른 서비스로 리디렉션됩니다. 응용 프로그램에는 명시적인 RequestMapping이 없습니다 (아직).

이제는 인터셉터가 호출 될 때 요청이 기본 Spring 오류 처리기로 리디렉션됩니다. 결과적으로 HttpServletRequest에 저장된 URI는 /error (효과적으로 원래 URI에 대한 액세스를 거부 함)으로 바뀝니다.

오류 처리기로 다시 라우팅되거나 원래의 URI를 가져 오기 전에 요청을 가로 챌 수있는 방법이 있습니까?

답변

1

편집 : 당신이 대신에 의존하지 않는 게 좋을 경우, 그렇지 않으면

@Component 
public class CustomFilter implements Filter { 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
      throws IOException, ServletException { 

     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 

     request.getSession().setAttribute("ORIGINAL_REQUEST_URI", request.getRequestURI()); 
     chain.doFilter(request, response); 

     // alternatively, ignore the last 2 lines 
     // and just do your redirects from here 
     // and don't continue the filter chain 
    } 

    @Override 
    public void destroy() {} 

    @Override 
    public void init(FilterConfig arg0) throws ServletException {} 

} 

:이 때문에 스프링 MVC는 더 매핑 요청을 처리하는 방식의

, 당신도 필터가 필요합니다 세션, you'll need to make the DispatcherServlet throw an exception in case no handler mapping is found는 다음 @ControllerAdvice 오류 처리기에서 리디렉션을 보내

@ControllerAdvice 
class NoHandlerFoundExceptionExceptionHandler { 

    @ExceptionHandler(value = NoHandlerFoundException.class) 
    public ModelAndView 
    defaultErrorHandler(HttpServletRequest req, NoHandlerFoundException e) throws Exception { 
    String uri = // resolve the URI 
    return new ModelAndView("redirect:" + uri); 
    } 
} 

하는 AV로 중복을 방지하려면 인터셉터와 오류 처리기 모두에서 호출 할 공통 클래스가 필요할 수 있습니다.

+0

리디렉션이 정상적으로 작동합니다. 문제는 요청에서 원래 URI가 필요하다는 것입니다. 원래의 URI에 대한'RequestMapping'이없는 경우, Spring은 자동으로 (?)를 디폴트 에러 컨트롤러로 리디렉션합니다. 이 리디렉션은'HttpServletRequest'의 URI를'/ error' (또는 그와 같은 것)로 변경합니다. 결과적으로 원래 URI에 더 이상 액세스 할 수 없기 때문에 (리디렉션 할 위치를 결정할 수 있습니다). 현재 해결 방법은'RequestMapping (path = "**")'로 간단한 컨트롤러를 만드는 것입니다.하지만 이것은 더러운 해킹처럼 보입니다. – irundaia

+0

아, 죄송합니다. 설명에 따르면 인터셉터의 리디렉션에도 불구하고 '/ 오류'로 리디렉션되는 중임을 이해했습니다. 내 답변을 업데이트 할 것이다, 나는 당신이 단지 요청 속성으로서 원래의 요청 URI를 저장하는'Filter'를 가지고 있어야한다고 생각한다. –

+0

도움이되는 희망. 컨트롤러를 사용하는 당신의 방법은 분명히 더 적은 작업을 필요로합니다. 솔직히 말해서 해킹이 적을 수도 있습니다 :) 또한, 리다이렉션을하는 중이라면, 대신에 '필터'구현을 사용하는 것이 좋습니다. 인터셉터/컨트롤러 접근법. –