我有一个struts2动作,通过获取一些请求参数,调用返回XML数据的远程服务,然后通过XSL转换数据并通过Stream Result返回结果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变量是线程安全的?或者是否有另一种我没有看到的解决方案?
答案 0 :(得分:0)
我只熟悉Struts 1,但请看看DonwloadAction。或者只使用普通的struts Action,将结果直接写入响应对象并返回null作为转发。
答案 1 :(得分:0)
我根本没有进入Struts 2,但是如果你真的必须返回“成功”结果并且无法直接写入输出,那么这似乎是一个使用ThreadLocal
的好地方保持您的流本地到当前线程。 (有关模式的更多信息,另请参阅线程本地存储上的Wikipedia article。)
答案 2 :(得分:0)
感谢Henning带领我朝着正确的方向前进。我没想过直接写入响应输出流,因为在struts2文档中没有提到它。
将响应直接写入输出流的好处是您不需要为inputStream创建实例对象。这会将所有数据保存在execute()方法中,这对其他线程是安全的。
这是一个修改后的动作类,它直接写入输出流并返回null结果。
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;
}
}
这似乎解决了我遇到的问题。