我在网页上有一个命令对话框,该对话框使用命令按钮来确认用户是否要运行后端脚本。如果用户确认要继续,则应该立即发出咆哮声,让他们知道脚本已开始。然后,脚本将运行,阻止所有其他进程,直到完成为止。完成后,应该再有一条咆哮消息,让用户知道脚本已完成。
xhtml代码设置如下:
<p:commandButton value="Yes Sure" actionListener="#{listBean.invokeBackend}"
onclick="PF('backendRun').hide()" update="invokeBackendGrowl"/>
这些属性不能同时执行。这些属性的执行顺序为 onclick ,然后是 actionlistener ,然后是 update 。由于我的动作侦听器项引用了阻止其他进程的功能,因此我需要在动作侦听器项完成之前执行update属性。
点击关闭命令对话框
更新可显示咆哮声的最新版本
actionlistener 执行bean方法,该方法使用流程生成器来确保脚本运行不中断。它还包含两个咆哮的Java代码(脚本开始的通知和脚本结束的通知)。由于脚本是单独运行的,因此这些咆哮声都在脚本完成后同时显示,而不是在脚本开始时立即显示开始的咆哮声。
动作侦听器项如下:
public void invokeBackend() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(<command for script to run>);
pb.redirectErrorStream(true);
File outputFile = new File(<location>);
pb.redirectOutput(outputFile);
Process p = pb.start();
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "Script Called!"));
p.waitFor();
context.addMessage(null, new FacesMessage("Completed", "Script Complete!"));
}
更新
此代码中只有一个线程,这个问题正在寻找一种方法来重新组织线程与其他动作有关的开始时间。
答案 0 :(得分:-2)
我使用以下解决方法解决了这个问题:
由于jsf总是会在update属性之前调用actionlistener,因此我修改了actionlistener的工作以排除进程阻止脚本。现在,命令按钮上的 actionlistener 会调用 reroute方法,该方法只执行第一个咆哮声,通知用户脚本已开始。然后运行update属性,显示第一个咆哮声。
然后,我引入一个远程命令来调用invokeBackend(),该方法与以前相同,只减去第一个咆哮声的代码。
xhtml代码现在如下:
<p:commandButton value="Yes Sure" actionListener="#{listBean.reroute()}"
onclick="PF('backendRun').hide();" update="invokeBackendGrowl" onsuccess="doAfter()" />
<p:remoteCommand name="doAfter" update="doneBackendGrowl" action="#{listBean.invokeBackend()}"/>
现在的Java代码如下:
public void invokeBackend() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(<command for script to run>);
pb.redirectErrorStream(true);
File outputFile = new File(<location>);
pb.redirectOutput(outputFile);
Process p = pb.start();
FacesContext context = FacesContext.getCurrentInstance();
p.waitFor();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Backend complete! Please check email for the output."));
}
public void reroute(){
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Backend invoked! ", "Please check back here for updates."));
}
简而言之,现在对代码进行拆分,以便reroute()保留脚本在invokeBackend()中阻止所有其他进程之前需要执行的代码。