3

是否有任何已知方法可以在单个 WebContainer 中将新的 SOAP 请求从一个 servlet 发送到另一个,而无需消耗额外的 Web 容器线程?

到目前为止,我已经尝试将 RequestDispatcher.include(request, response) 与自定义请求和响应一起使用,这样我就可以提供自己的输入并拦截被调用者的输出。有了这个,我可以毫无问题地拦截输出(使用写入缓冲区的自定义 HttpServletResponse 类),但我无法使用此方法发送自定义输入。我正在使用 HttpServletRequestWrapper 的扩展来向第三方应用程序提供我自己的输入(而不是对我的应用程序的原始请求),但是似乎 WebSphere 或 Axis 正在丢弃我的包装器,因此我得到一个 SOAP 错误而不是有效的回应。为了清楚起见,我不需要将原始请求转发给被调用者(这是一个 JSONP GET 请求),

我应该尝试这种方法的变体吗?是否有完全不同的方式在单个 Web 容器中发送请求?

非常感谢回复的人。

对于上下文,我正在编写一个在 WebSphere Application Server 上运行的 JSON/REST Web 服务,它反过来通过 Axis 2 上的 SOAP 调用第三方产品。不幸的是,这个第三方产品只能通过 SOAP HTTP 接口获得,尽管它本身是在同一个 WebSphere Web 容器中运行的 Java servlet。

以前,我一直使用基于第三方产品的 WSDL 的 SOAP 代理生成器生成的 HTTP 代理调用此应用程序。这很好用,但这意味着对我的服务的一次调用又会消耗两个 Web 容器线程,这是一个严重的漏洞。一旦 Web 容器线程池已满,它就会保持满状态,因为对我的 servlet 的请求会一直保持线程,直到第三方应用程序响应为止,因为没有线程可用于处理我的 servlet 发出的 HTTP 请求,所以它无法做到这一点。

更新: 我已经做了一些进一步的测试,并且能够成功地将这种类型的转发到我的 REST 服务。我可以使用合成的 ServletRequest 和 ServletResponse 查询我的 REST/JSON 服务,因此如果我调用的产品不使用 Axis SOAP 接口,我就可以实现我的原始目的。看起来 Axis 在寻找 SOAPAction 标头的位置与我预期的不同,因为我总是得到“找不到 SOAPAction 标头!” 尽管我在合成请求中添加了 SOAPAction 标头,但仍返回错误消息(我已验证实际上添加了 SOAPAction 标头)。

4

1 回答 1

0

事实证明,由于“缺少” SOAPAction 标头,我无法让该服务与 Axis 一起工作的原因与 WebSphere 或 Axis 完全无关。这是一个 ConcurrentHasMap,它以某种方式比较两个等效字符串并说它们不同,因此当 Axis 查找 SOAPAction 标头时,它从未返回。为了解决这个问题,我简单地测试了关于“SOAPAction”的查询并对响应进行了硬编码。

因此,为了将来参考,这里是我使用的一般设置。

  1. 创建一个实现类,该类实现HttpServletRequest包装另一个HttpServletRequest要在构造函数中提供的类。在此类中,该getHeader方法被重写以捕获对 SOAPAction 标头的请求,其他标头请求可能被转发到原始请求(Axis 似乎不寻找 SOAPAction 标头以外的任何内容)。我还getInputStream重写了返回我自己的 ServletInputStream 实现的方法,该实现只是使用固定文本编码从字节缓冲区中读取,以及getContentLength返回与我的数据一致的长度的方法。

  2. 创建一个实现 HttpServletResponse 的类,该类只正确实现 getWriter 和 getOutputStream 方法。该getOutputStream方法返回一个自定义ServletOutputStream实现,该实现将其输出记录到字节缓冲区。该getWriter方法返回了一个特殊的 PrintWriter,它写入了由 返回的同一个 ServletOutputStream getOutputStream,除了这个 writer在写入后总是需要刷新 - 我不知道为什么必须这样。

  3. 在使用 发送请求之前RequestDispatcher.include(request, response),我将我的合成文件包裹HttpServletRequest在一个HttpServletRequestWrapper中,奇怪的是这似乎有帮助。然后我RequestDispatcher.include(request, response)以通常的方式使用,并从我的自定义 ServletOutputStream 的字节缓冲区中读取 SOAP 服务的输出,以像我发出 HTTP 请求一样进行处理。

于 2012-08-28T14:02:41.180 回答