2009-06-25 20 views
0

我有一个struts2动作,它通过接收一些请求参数来响应AJAX请求,调用返回XML数据的远程服务,然后通过XSL转换数据并返回结果XHTML通过流结果。响应根据给定的参数而不同。通过struts2动作处理多个同时发生的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动作,有时候响应是完全空白的(不应该发生),有时响应会在开始或结束时被一些随机量切断,有时响应会被切换,所以一个A收到错误的答复JAX请求者。我知道这是一个线程安全问题,我已经将所有重要的变量定义移动到execute()方法中,以使它们不是实例变量(因此被所有变量共享)。唯一有趣的变量是一个实例变量,它是inputStream,我把它看作是我的问题的原因。

有没有办法使inputStream变量线程安全?还是有另一种解决方案,我没有看到?

回答

0

感谢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; 
    } 
} 

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

0

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

0

我根本没有进入Struts 2,但是如果你真的必须返回“成功”结果并且没有办法直接写入输出,这看起来像是一个使用ThreadLocal来保持你的本地流到当前线程。 (有关该模式的更多信息,另请参见线程本地存储器上的Wikipedia article。)

+0

我不需要返回“成功”,而只是受到struts2的限制,只要我可以或不可以做。如果我可以找到一种方法直接输出而不必使用实例变量,那么我会这样做。 – 2009-06-25 20:50:17