【问题标题】:Strut2 execAndWait interceptor + JSON result type + Dojo dijit.ProgressBar = AJAX Progress BarStrut2 execAndWait 拦截器 + JSON 结果类型 + Dojo dijit.ProgressBar = AJAX 进度条
【发布时间】:2010-11-01 21:18:39
【问题描述】:

我正在使用 Dojo ProgressBar 来使用 execAndWait 拦截器在 Struts2 中显示一个长时间运行的进程。 execAndWait 拦截器为每个返回等待结果的调用将操作放在值堆栈上。但是,当结果类型为 JSON 时,动作只有动作的默认值。

这是我的 struts 动作配置
(我尝试对结果名称进行通配符,但这不起作用)
注意:我必须将我的 JSON 包装在一个 textarea 中,因为 Dojo 的 iframe.send 期望它被包装在一个文本区域。


<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 拦截器的代码以获取更多线索。

【问题讨论】:

    标签: ajax json dojo struts2 progress-bar


    【解决方案1】:

    看了JSONResult之后发现问题了。

    当您在 JSON 上设置“根”对象时,它会在值堆栈中查找值。如果不是,它会查看 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 上的操作之前检查值堆栈上的操作。

    【讨论】:

    • 您是否有机会修改您的答案以了解 FileProcessor 是什么?无论是源代码,甚至是其实现方式的摘要都会非常有帮助
    猜你喜欢
    • 1970-01-01
    • 2013-05-15
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    相关资源
    最近更新 更多