【问题标题】:Sending a new request to another servlet in the same web container without using an extra thread在不使用额外线程的情况下向同一个 Web 容器中的另一个 servlet 发送新请求
【发布时间】:2012-08-24 06:45:09
【问题描述】:

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

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

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

非常感谢回复的人。

就上下文而言,我正在编写一个 JSON/REST Web 服务以在 WebSphere Application Server 上运行,而后者又通过 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 标头)。

【问题讨论】:

  • 顺便说一句,这个问题是特定于 WebSphere 6.x 的。我听说 WebSphere 7 和更高版本正式支持从等待外部方的请求中分离线程,从而避免线程饥饿。

标签: java servlets websphere


【解决方案1】:

事实证明,由于“丢失”的 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,它写入由 getOutputStream 返回的同一个 ServletOutputStream,除了这个 writer 总是 需要在写入后刷新 - 我不知道为什么必须这样。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    相关资源
    最近更新 更多