以下代码来自支持bean。 async()
从视图中调用<f:event listener="#{nextBean.async}" type="preRenderView"/>
。由于我不希望此操作延迟视图的呈现,因此它会在EJB中触发@Asynchronous
- 带注释的方法,返回Future<Boolean>
。
只要此操作正在运行,我希望UI被阻止,因此我执行<p:remoteCommand>
触发ready()
,检查是否有Future
- 对象的结果,这意味着异步方法具有完成然后取消阻止UI
问题:异步方法似乎被ready()
第二次调用。我怎样才能实现我的目标?
支持bean:
package mypackage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.java.Log;
@ManagedBean
@ViewScoped
@Getter
@Setter
public class NextBean {
@EJB private AsyncBean asyncBean;
private Future<Boolean> ready;
public void async() {
ready = asyncBean.async();
}
public void ready() {
try {
while (ready.get() != true) {
Thread.sleep(300);
}
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Facelets代码:
<html xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body id="wholeView">
<f:metadata>
<f:event listener="#{nextBean.async}" type="preRenderView"></f:event>
</f:metadata>
<p:blockUI id="blockui" block=":wholeView" widgetVar="blockUI">
please wait
</p:blockUI>
<h:form>
<p:remoteCommand onstart="blockUI.show();"
name="doIt"
id="dooo"
process="@this"
action="#{nextBean.ready}"
oncomplete="blockUI.hide();"
autoRun="true"
/>
</h:form>
CONTENT
</h:body>
</html>
EJB:
package mypackage;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
import lombok.extern.java.Log;
@Stateless
@Log
public class AsyncBean {
@Asynchronous
public Future<Boolean> async(){
try {
Thread.sleep(3000);
return new AsyncResult<Boolean>(true);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
更新
1.用户从外部页面定向到视图(作为支付过程的一部分)
2.在请求视图时,应该执行业务逻辑,这不会延迟视图的呈现,而是在执行业务逻辑时阻止它的UI。
答案 0 :(得分:2)
很抱歉,但这种方法没有任何意义。
每个HTTP请求都会触发preRenderView
事件。
<p:remoteCommand autoRun="true">
计为一个HTTP请求。
因此,实际上,当您打开此页面时,会触发2个HTTP请求。这解释了为什么preRenderView
侦听器方法被调用两次。
@Asynchronous
完全没用。您在调用Future#get()
方法的同一个线程中调用@Asynchronous
。你在电话和Future#get()
之间没有做任何有用的事情。基本上,你是阻塞当前线程并告诉它等到另一个线程完成。当前的线程基本上是无所事事而且无法用于其他任务,这是一个很大的浪费。这有什么意义?为什么不通过删除@Asynchronous
来完成当前线程中的工作?
您没有说明您认为此将成为解决方案的具体功能要求,因此很难给出合适的答案或推动您朝着正确的方向前进。我想你需要push。