【问题标题】:Spring boot HandlerInterceptor loadbalancingSpring boot HandlerInterceptor 负载均衡
【发布时间】:2017-01-10 16:11:45
【问题描述】:

我正在使用 Spring Boot 实现(某种)负载平衡 HandlerInterceptor

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,我们要么重定向到一个服务,要么重定向到另一个服务。该应用程序没有任何明确的RequestMappings(目前)。

现在的问题是,当调用拦截器时,请求被重定向到默认的 Spring 错误处理程序。因此,HttpServletRequest 中存储的 URI 被 /error 替换(有效地拒绝了对原始 URI 的访问)。

有没有办法在请求被重新路由到错误处理程序(或获取原始 uri)之前拦截请求?

【问题讨论】:

    标签: java spring spring-mvc spring-boot


    【解决方案1】:

    编辑:

    由于 Spring MVC 处理没有映射的请求的方式,您要么需要一个过滤器:

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

    否则,如果您不想依赖会话 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);
      }
    }
    

    为避免重复,您可能希望有一个公共类,您将从拦截器和错误处理程序中调用它。

    【讨论】:

    • 重定向工作正常。问题是我需要请求中的原始 URI。如果原始 URI 没有 RequestMapping,Spring 将自动重定向(?)到默认的错误控制器。此重定向还将 HttpServletRequest 中的 URI 更改为 /error(或类似的)。结果,我无法再访问原始 URI(以确定我需要重定向到的位置)。我目前的解决方法是使用带有RequestMapping(path = "**") 的简单控制器,但这似乎是一个肮脏的黑客。
    • 啊,抱歉,根据您的描述,我了解到尽管拦截器重定向,但仍会重定向到 /error。然后我会更新我的答案,我认为您应该可以使用 Filter 将原始请求 URI 保存为请求属性。
    • 那里,希望对您有所帮助。你使用控制器的方式肯定需要更少的工作,如果我可以坦率地说,可能不是一个黑客:) 另外,如果你只是做重定向,你可能最好使用 Filter 实现而不是使用拦截器/控制器方法。
    • 确实有帮助。非常感谢您的努力:)
    • 别提了,一路上我也学到了一些东西:)
    猜你喜欢
    • 2016-01-03
    • 2021-01-10
    • 2017-03-24
    • 2015-07-26
    • 1970-01-01
    • 2018-07-06
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多