2010-11-01 69 views
0

我正在使用Dojo ProgressBar在Struts2中使用execAndWait拦截器显示长时间运行的进程。 execAndWait拦截器将操作置于每个调用返回等待结果的值栈上。但是,当结果类型为JSON时,该操作仅具有操作的默认值。Strut2 execAndWait拦截器+ JSON结果类型+ Dojo dijit.ProgressBar = AJAX进度条

这里是我的支柱作用的配置
(我试过外卡,结果名字,但没有工作)
注:我有我的包裹在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

看到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类来保存


public class LongRunningImpl implements LongRunning { 
    private Integer percentComplete = 0; 
    private String processMessage = "Uploading file..."; 
    private boolean running = true; 
... 
} 

我使用该对象在我的行动LongRunning信息:


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结果对象应该在默认返回ActionInvocation上的动作之前检查值栈上的动作。

+0

任何机会,你可以修改你的答案进入什么FileProcessor?无论是源代码,还是它的实现摘要都会非常有帮助 – NobodyMan 2011-03-15 21:33:47