我正在使用Dojo ProgressBar使用execAndWait拦截器在Struts2中显示一个长时间运行的进程。 execAndWait拦截器将操作放在每个返回等待结果的调用的值堆栈上。但是,当结果类型为JSON时,操作仅具有操作的默认值。
这是我的struts动作配置
(我试图通过万能卡结果名称,但那不起作用)
注意:我必须将我的JSON包装在textarea中,因为Dojo的iframe.send希望将它包装在textarea中。
<action name="upload" class="ProcessFileAction" method="upload">
<interceptor-ref name="agfStack" />
<interceptor-ref name="execAndWait">
<param name="delay">1000</param>
<param name="delaySleepInterval">500</param>
</interceptor-ref>
<result name="wait" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
<result name="success" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
<result name="error" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
</action>
这是我的JSP
注意:我必须使用iFrame.send操作,因为我正在上传文件。因为我的struts结果对于每次连续调用的初始等待返回都是相同的,所以我也必须使用iframe.send进行AJAX调用(而不是xhrGet)。这是因为iframe.send期望JSON包装在文本区域中,而xhrGet则不包含。
<%@taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<script type="text/javascript">
dojo.require("dojo.io.iframe");
dojo.require("dijit.ProgressBar");
dojo.require('dojox.timing');
var t = new dojox.timing.Timer(<tiles:getAsString name="refreshTime" />);
t.onTick = function() {
dojo.io.iframe.send({
url: '<s:url action="upload" namespace="/" />',
method: "POST",
handleAs: "json",
load: function(response, ioArgs){
if(response.running) {
var progressPercent = response.percentComplete + "%";
var reportText = response.processMessage;
var uploadProgesssBar = dijit.byId("uploadProgress");
if(uploadProgesssBar == null) {
return;
}
uploadProgesssBar.update({progress:progressPercent, report:function() {return reportText;}});
}
else {
showById("progressDialogButtonDiv");
t.stop();
}
},
error: function(response, ioArgs) {
t.stop();
var progressPercent = response.percentComplete + "%";
var reportText = response.processMessage;
var uploadProgesssBar = dijit.byId("uploadProgress");
if(uploadProgesssBar == null) {
return;
}
uploadProgesssBar.update({progress:progressPercent, report:function() {return reportText;}});
showById("progressOkButton");
}
});
};
function showProgressBar() {
hideById("uploadForm");
showById("progressBar");
}
function hideProgressBar() {
hideById("progressBar");
showById("uploadForm");
}
function submitAndShowProgress(submitForm) {
dojo.io.iframe.send({
form: submitForm,
handleAs: "json",
load: function(response, ioArgs) {
submitForm.reset();
var progressPercent = response.percentComplete + "%";
var reportText = response.processMessage;
if(response.running) {
showProgressBar();
var uploadProgesssBar = dijit.byId("uploadProgress");
if(uploadProgesssBar == null) {
return;
}
uploadProgesssBar.update({progress:progressPercent, report:function() {return reportText;}});
t.start();
}
else {
createAndShowAlertDialog(reportText, "");
}
return response;
},
error: function(response, ioArgs) {
t.stop();
hideProgressBar();
createAndShowAlertDialog(response.processMessage, "An Error Occurred");
return response;
}
});
return false;
}
</script>
<div id="progressBar" class="hidden loading">
<div dojoType="dijit.ProgressBar" style="width:400px" jsId="uploadProgress" id="uploadProgress" annotate="true"></div>
<div class="hidden actionButtons" id="progressOkButton">
<button style="position: relative; left: 42px;" dojoType="dijit.form.Button" onClick="hideProgressBar(); return false;">Ok</button>
</div>
</div>
<s:form action="upload" namespace="/" enctype="multipart/form-data" id="uploadForm" method="post" onsubmit="return submitAndShowProgress(this);">
<s:file name="file" id="file" label="File" />
<s:submit id="submit" name="submit">Upload</s:submit>
</s:form>
这是我的行动:
的(修剪)
public class ProcessFileAction implements LongRunning {
String processMessage = "Uploading...";
Integer percentComplete = 0;
Boolean running = true;
private FileProcessor fileProcessor;
private File file;
private String fileContentType;
private String fileFileName;
public String upload() throws Exception {
setProcessMessage("Processing File...");
setPercentComplete(10);
try {
if(!getFile().exists()) {
getFile().createNewFile();
}
File processedFile = getFileProcessor().process(getFile(), this);
} catch(Exception e) {
e.printStackTrace();
setProcessMessage("An error occurred while processing your file.");
setPercentComplete(100);
setRunning(false);
return ERROR;
}
setProcessMessage("Process Complete!");
setPercentComplete(100);
setRunning(false);
return SUCCESS;
}
...
}
public interface LongRunning {
public void setProcessMessage(String processMessage);
public String getProcessMessage();
public void setPercentComplete(Integer percentComplete);
public Integer getPercentComplete();
public void setRunning(boolean running);
public boolean isRunning();
}
我将查看JSON结果类型的代码和ExecAndWait拦截器以获取更多线索。
答案 0 :(得分:0)
在查看JSONResult
后,我发现了问题。
在JSON上设置“root”对象时,它会在值堆栈中查找值。如果没有,它会查看ActionInvocations操作(不与ExecAndWait Intercepror一起使用)。
public void execute(ActionInvocation invocation) throws Exception {
...
String json;
Object rootObject;
if (this.enableSMD) {
// generate SMD
rootObject = this.writeSMD(invocation);
} else {
// generate JSON
if (this.root != null) {
ValueStack stack = invocation.getStack();
rootObject = stack.findValue(this.root);
} else {
rootObject = invocation.getAction();
}
}
...
}
因此,我创建了一个LongRunningImpl类来保存LongRunning信息
public class LongRunningImpl implements LongRunning {
private Integer percentComplete = 0;
private String processMessage = "Uploading file...";
private boolean running = true;
...
}
我在行动中使用了这个对象:
public class ProcessFileAction {
LongRunning longRunning;
private FileProcessor fileProcessor;
private File file;
private String fileContentType;
private String fileFileName;
public String upload() throws Exception {
getLongRunning().setProcessMessage("Processing File...");
getLongRunning().setPercentComplete(10);
try {
if(!getFile().exists()) {
getFile().createNewFile();
}
File processedFile = getFileProcessor().process(getFile(), getLongRunning());
} catch(Exception e) {
e.printStackTrace();
getLongRunning().setProcessMessage("An error occurred while processing your file.");
getLongRunning().setPercentComplete(100);
getLongRunning().setRunning(false);
return ERROR;
}
getLongRunning().setProcessMessage("Process Complete!");
getLongRunning().setPercentComplete(100);
getLongRunning().setRunning(false);
return SUCCESS;
}
...
}
然后在我的结果上设置一个根对象:
<action name="upload" class="ProcessFileAction" method="upload">
<interceptor-ref name="agfStack" />
<interceptor-ref name="execAndWait">
<param name="delay">1000</param>
<param name="delaySleepInterval">500</param>
</interceptor-ref>
<result name="wait" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="root">longRunning</param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
<result name="success" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="root">longRunning</param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
<result name="error" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
<param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
<param name="root">longRunning</param>
<param name="includeProperties">percentComplete,processMessage,running</param>
</result>
</action>
现在一切正常!我可能会将此列为Struts2的缺陷,但我不确定它是如何被接收的。我认为JSON Result对象应该在默认返回ActionInvocation上的操作之前检查值堆栈上的操作。