我想通过在FacesContext
类的FacesContext.getCurrentInstance()
方法中调用run()
来获取Runnable
,但它会返回null
。
public class Task implements Runnable {
@Override
public void run() {
FacesContext context = FacesContext.getCurrentInstance(); // null!
// ...
}
}
这是如何引起的?如何解决?
答案 0 :(得分:13)
FacesContext
作为ThreadLocal
变量存储在负责调用FacesServlet
的HTTP请求的线程中,FacesContext
负责创建FacesContext
。该线程通常仅通过JSF托管bean方法。 Runnable
在该线程生成的其他线程中不可用。
在其他线程中,您实际上也不需要它。此外,当您的线程启动并独立运行时,底层HTTP请求将立即继续处理HTTP响应然后消失。无论如何,你将无法对HTTP响应做些什么。
您需要以不同方式解决问题。问问自己:你需要什么?获取一些信息?在构建过程中,只需将 信息传递给public class Task implements Runnable {
private Work work;
public Task(Work work) {
this.work = work;
}
@Override
public void run() {
// Just use work.
}
}
。
以下示例假定您要访问线程中的某个会话作用域对象。
Work work = (Work) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("work");
Task task = new Task(work);
// ...
Runnable
但是,如果您最终需要通知客户,例如线程的工作已经完成,那么你应该寻找一个不同于添加面部消息左右。答案是使用“推”。这可以通过SSE或websockets实现。在这个相关问题中可以找到具体的websockets示例:Real time updates from database using JSF/Java EE。如果您碰巧使用PrimeFaces,请查看
<p:push>
。如果您碰巧使用OmniFaces,请查看<o:socket>
。
无关,手动创建{{1}}并在Java EE Web应用程序中手动生成线程令人震惊。前往以下Q&amp; A,了解所有注意事项及其实际应如何实现: