2009-06-25 56 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