2010-11-01 52 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