【发布时间】:2011-04-24 09:24:59
【问题描述】:
我正在尝试创建一个 HttpServlet,它将所有传入请求按原样转发到另一个在不同域上运行的 serlvet。
如何做到这一点? RequestDispatcher 的 forward() 只在同一台服务器上运行。
编辑:我不能引入任何依赖项。
【问题讨论】:
我正在尝试创建一个 HttpServlet,它将所有传入请求按原样转发到另一个在不同域上运行的 serlvet。
如何做到这一点? RequestDispatcher 的 forward() 只在同一台服务器上运行。
编辑:我不能引入任何依赖项。
【问题讨论】:
当它不在同一个 ServletContext 或同一个/集群网络服务器中运行时,您不能,其中 web 应用程序配置为共享 ServletContext(如果是 Tomcat,请检查 crossContext 选项)。
您必须通过HttpServletResponse.sendRedirect() 发送重定向。如果您实际关心的是在新 URL 上重用查询参数,只需将它们一起重新发送。
response.sendRedirect(newURL + "?" + request.getQueryString());
或者当它是 POST 时,发送 HTTP 307 重定向,客户端将在新 URL 上重新应用相同的 POST 查询参数。
response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("Location", newURL);
Update 根据 cmets,这显然不是一个选项,因为您想隐藏 URL。在这种情况下,您必须让 servlet 充当代理。您可以使用 HTTP 客户端执行此操作,例如Java SE 提供了java.net.URLConnection (mini tutorial here) 或更方便的Apache Commons HttpClient。
如果是 GET,就这样做:
InputStream input = new URL(newURL + "?" + request.getQueryString()).openStream();
OutputStream output = response.getOutputStream();
// Copy.
或者如果是 POST:
URLConnection connection = new URL(newURL).openConnection();
connection.setDoOutput(true);
// Set and/or copy request headers here based on current request?
InputStream input1 = request.getInputStream();
OutputStream output1 = connection.getOutputStream();
// Copy.
InputStream input2 = connection.getInputStream();
OutputStream output2 = response.getOutputStream();
// Copy.
请注意,您可能需要捕获/替换/更新 HTML 响应中的相关链接(如果有)。 Jsoup 可能对此非常有帮助。
【讨论】:
正如其他人指出的那样,您想要的是代理。您的选择:
找到一个可以执行此操作的开源 Java 库。那里有一些,但我没有使用过任何一个,所以我不能推荐任何一个。
自己写。应该不会太难,只要记住处理诸如传递所有标头和响应代码之类的东西。
在 Apache 2.2 中使用代理模块。这是我会选择的,因为我已经知道它工作可靠。
【讨论】:
Jetty 有一个示例 ProxyServlet 实现,它在后台使用 URL.openConnection()。随意按原样使用或用作您自己实施的灵感。 ;-)
或者您可以使用 Apache HttpClient,请参阅 tutorial。
【讨论】: