使Java servlet充当代理的代码?

IAm*_*aja 22 java servlets reverse-proxy web-applications http

我有两个Java Web应用程序,它们具有映射到特定URL的单个servlet:

red.war/
    WEB-INF/classes
        com.me.myorg.red.RedServlet (maps to http://red.example.com/doStuff)
blue.war/
    WEB-INF/classes
        com.me.myorg.blue.BlueServlet (maps to http://blue.example.com/doStuff)
Run Code Online (Sandbox Code Playgroud)

我想把这些应用程序(我称之为"后端应用程序")放在"代理应用程序"(servlet)后面,这将决定这两个应用程序中的哪一个最终将服务于客户端请求.

此代理Web应用程序将接收传入的HTTP请求,并确定将请求转发到的2个"后端应用程序"(红色或蓝色)中的哪一个.然后,请求将转发到http://red.example.com/doStuff(或然后由其处理RedServlet#doGet(...))或http://blue.example.com/doStuff(然后由其处理BlueServlet#doGet(...)).然后,来自后端应用程序的返回响应(再次,RedServlet#doGet(...)或者BlueServlet#doGet(...))将返回到代理servlet,并最终返回给客户端.

换句话说,在伪代码中:

public class ProxyServlet extends HttpServlet {
    @Override
    public doGet(HttpServletRequest request, HttpServletResponse response) {
        String forwardingAddress;
        if(shouldBeRed(request))
            forwardingAddress = "http://red.example.com/doStuff";
        else
            forwardingAddress = "http://blue.example.com/doStuff";

        PrintWriter writer = response.getWriter();

        writer.write(getResponseFromBackend(forwardingAddress, request));
    }

    private String getResponseFromBackend(String addr, HttpServletRequest req) {
        // Somehow forward req to addr and get HTML response...
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?如果是这样,我需要编写的代码和代码才能使其工作?

ult*_*ate 10

您可以使用a RequestDispatcher以下列方式转发您的请求:

RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(forwardingAddress);

// here you have the choice whether to use include(..) or forward(..) see below
if(useInclude)
    dispatcher.include(httpRequest, httpResponse);
else
    dispatcher.forward(httpRequest, httpResponse);
Run Code Online (Sandbox Code Playgroud)

... useInlcude使用以下选项设置为您选择的位置:

  • include
    这可能就是你想要做的事情:将内容加载forwardingAdress到你的响应中.
    • 这意味着您甚至可以将多个目标包含在一个响应中.
    • 客户端甚至不会实现此过程,也不需要能够查看目标文档.
  • 转发
    发送到forwardingAddress.这将告诉客户端向指定的URL 提交新请求.
    • 如果您在带有开发人员工具的浏览器中执行此操作,您将看到第二个请求.
    • 客户端必须能够查看并加载目标URL.
    • 您只能转发到单个目标.

请参阅以下链接:

  • RequestDispatcher javadoc,特别是对于注释:
    • 应在将响应提交给客户端之前调用forward(在刷新响应正文输出之前).如果响应已经提交,则此方法抛出IllegalStateException.响应缓冲区中的未提交输出在转发之前自动清除.
    • include:请求和响应参数必须是传递给调用servlet的服务方法的相同对象,或者是包装它们的ServletRequestWrapper或ServletResponseWrapper类的子类.
  • URLRewriteFilter示例
    虽然这个例子是用一个Filter而不是一个Servlet行为来实现的(注意:这个例子是我的框架的一部分,因此包含了父类中的一些开销.请看看相关部分...... )

  • 我认为只有当"后端"servlet部署在同一个应用程序上时,此解决方案才有效.由于红色和蓝色servlet部署在不同的主机中,因此获取其Context的Dispatcher可能是不可能的.查看更多解释http://stackoverflow.com/questions/4889113/how-to-forward-request-from-web1-servlet-to-web2-servlet (5认同)
  • 你说的 forward 是错误的:“这会告诉客户端向指定的 URL 提交一个新请求。” 这不是 sendRedirect 命令 (2认同)