我需要编写一个 servlet,它基本上只是将每个传入请求代理到不同主机上的相同 URL 路径。这是我使用 Apache Commons Http Client 4.1.3 得出的结论:

@WebServlet("/data/*") 
public class ProxyServlet extends HttpServlet { 
 
  protected void doGet (HttpServletRequest request, HttpServletResponse response) 
  throws ServletException, IOException { 
    HttpClient client = new DefaultHttpClient(); 
    try { 
      String url = getMappedServiceUrlFromRequest(request); 
      HttpGet get = new HttpGet(url); 
      copyRequestHeaders(request, get); 
 
      HttpResponse getResp = client.execute(get); 
      response.setStatus(getResp.getStatusLine().getStatusCode()); 
      copyResponseHeaders(getResp, response); 
 
      HttpEntity entity = getResp.getEntity(); 
      if (entity != null) { 
        OutputStream os = response.getOutputStream(); 
        try { 
          entity.writeTo(os); 
        } finally { 
          try { os.close(); } catch (Exception ignored) { } 
        } 
      } 
    } catch (Exception e) { 
      throw new ServletException(e); 
    } finally { 
      client.getConnectionManager().shutdown(); 
    } 
  } 
 
  private void getMappedServiceUrlFromRequest (...) 
  private void copyResponseHeaders (...) 
  private void copyRequestHeaders (...) 
} 

这在第一次调用 servlet 时工作得很好。然而,在第一次之后,servlet 在 client.execute(get) 行挂起。

有很多关于“HttpClient 执行挂起”的 Google 搜索结果,其中大部分建议使用 ThreadSafeClientConnManager 的实例。试过了,遗憾的是没有帮助。

我已经花了几个小时在谷歌上搜索这个问题,但我还没有找到任何可以解决它的方法。我非常感谢任何关于我在这里做错的指示。

请您参考如下方法:

我建议你用艰难的方式来做这件事。只需编写一个执行重定向的过滤器

或者甚至只是一个在端口上监听并来回复制字节的 TCP 服务器。您实际上根本不需要在代理中参与 HTTP 协议(protocol),除非您正在实现 CONNECT 命令,在这种情况下,这是您需要了解的唯一 HTTP 部分,它的回复是您唯一需要的 HTTP 响应了解。其他一切都只是字节。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!