【问题标题】:Handling many simultaneous AJAX requests with a struts2 action使用 struts2 操作处理许多同时发生的 AJAX 请求
【发布时间】:2009-06-25 19:06:30
【问题描述】:

我有一个 struts2 操作,它通过获取一些请求参数、调用返回 XML 数据的远程服务、然后通过 XSL 转换数据并通过流结果返回结果 XHTML 来响应 AJAX 请求。响应因给定参数而异。

这是取出一堆东西的动作类:

public class ServiceHandler extends ActionSupport {
    private ByteArrayInputStream inputStream;

    public String execute(){

        String response = "";

        // Get request parameters
        // Make a request to a remote server via an http connection
        // Transform result via XSL

        //uses dom4j for XML/XSL stuff
        //this should never be empty
        response = resultDoc.asXML();

        inputStream = new ByteArrayInputStream(response.getBytes()); 
        return "success";
    }

    public ByteArrayInputStream getInputStream(){
        return inputStream;
    }
}

这里是重要的 struts.xml 位:

<action name="sh" class="ServiceHandler">
    <result name="success" type="stream">
        <param name="contentType">text/html</param>
        <param name="contentDisposition">inline;filename="response.html"</param>
        <param name="bufferSize">1024</param>
        <param name="allowCaching">false</param>
    </result>
</action>

我的问题是,当我有多个请求同时进行时,都调用 ServiceHandler 操作,有时响应完全空白(不应该发生),有时响应在开始或结束时被一些随机切断数量,有时响应会被切换,因此 AJAX 请求者会收到错误的响应。

我知道这是一个线程安全问题,我已经将所有重要的变量定义移到了 execute() 方法中,因此它们不是实例变量(因此被所有人共享)。唯一有趣的实例变量是 inputStream,我将其视为问题的原因。

有没有办法让 inputStream 变量成为线程安全的?还是有其他我没有看到的解决方案?

【问题讨论】:

    标签: java multithreading tomcat struts2


    【解决方案1】:

    我只熟悉 Struts 1,但看看 DonwloadAction。或者只是使用一个普通的struts Action,将结果直接写入响应对象并返回null作为forward。

    【讨论】:

      【解决方案2】:

      我根本不喜欢 Struts 2,但如果你真的必须返回“成功”结果并且无法直接写入输出,这看起来是使用 ThreadLocal 保存的好地方您当前线程的本地流。 (有关该模式的更多信息,请参阅线程本地存储上的Wikipedia article。)

      【讨论】:

      • 我不需要返回“成功”,并且只受 struts2 的限制,只要我能做什么和不能做什么。如果我能找到一种无需使用实例变量而直接输出的方法,那么我会这样做。
      • 找到了办法,直接写好像解决了我的问题。
      【解决方案3】:

      感谢 Henning 引导我朝着正确的方向前进。我没有想过直接写入响应输出流,因为它在 struts2 文档中的任何地方都没有提到。

      将响应直接写入输出流的好处是不需要为 inputStream 创建实例对象。这将所有数据保存在 execute() 方法中,对其他线程是安全的。

      这里是一个修改过的动作类,直接写入输出流并返回一个空结果。

      import javax.servlet.http.HttpServletResponse;
      import org.apache.struts2.ServletActionContext;
      
      public class ServiceHandler extends ActionSupport {
          public String execute(){
      
              String response = "";
      
              // Get request parameters
              // Make a request to a remote server via an http connection
              // Transform result via XSL
      
              //uses dom4j for XML/XSL stuff
              //this should never be empty
              response = resultDoc.asXML();
      
              HttpServletResponse httpResponse = ServletActionContext.getResponse();
              try{
                  httpResponse.getOutputStream().print(response);
              }
              catch(IOException e){
                  return "failure";
              }
      
              return null;
          }
      }
      

      这似乎解决了我遇到的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-21
        • 2015-03-12
        • 1970-01-01
        • 2019-09-22
        • 2014-10-11
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        相关资源
        最近更新 更多