【发布时间】:2023-03-26 06:22:01
【问题描述】:
在 JSF2 中,我需要在 PostConstruct 期间由 ClassB 更新 bean ClassA, 然后显示更新的值。 我的问题是 ClassA 的 getter 在 ClassB 是 PostConstructed 之前被调用。
我的输出:
ValX:
ValY: toto
价值:42
我想要的输出:
ValX:42
ValY: toto
价值:42
在构建视图ID之前没有创建所有bean是否正常?
在调用 getter 之前更新 ClassA 的正确解决方案是什么?
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class ClassA implements Serializable {
private String valX;
@PostConstruct
public void init() {
System.out.println("init ClassA");
}
public String getValX() {
System.out.println("get ValX");
return valX;
}
public void setValX(String valX) {
System.out.println("set ValX");
this.valX = valX;
}
}
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class ClassB implements Serializable {
@ManagedProperty(value = "#{classA}")
private ClassA classA;
private String valY = "toto";
@PostConstruct
public void init() {
System.out.println("init ClassB");
classA.setValX("42");
}
public ClassA getClassA() {
return classA;
}
public void setClassA(ClassA classA) {
this.classA = classA;
}
public String getValY() {
return valY;
}
public void setValY(String valY) {
this.valY = valY;
}
}
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
</h:head>
<h:body>
ValX: #{classA.valX}<br/>
ValY: #{classB.valY}<br/>
ValX: #{classA.valX}<br/>
</h:body>
</html>
【问题讨论】:
-
这不是一个答案,但你到底为什么想要这个?如果您解释用例,有人可能会为您提供一个没有代码味道的替代方案。关于您的观点:JSF 解析您的 xhtml 并从中生成代表您的 EL 表达式的对象。他们在不同的时间得到评估,并且没有保证的顺序。
-
@mabi:事实上 ClassA 用于显示在其他 bean 初始化期间发生的错误。它是 ui:composition 使用的 xhtml 文件的一部分,因此它不了解其他 bean,但必须由它们更新。
-
classA会做FacesMessage未涵盖的任何事情吗?您可以使用omnifaces 的Messages 助手轻松地为前端添加新消息。如果有更多逻辑,我会添加 CDI 事件并让classA通过@Observe一个方法来监听它们。 -
我尝试使用消息,但如果 o:messages 标记在 ValY: #{classB.valY} 之前,则消息被视为未处理(并且不会在生产环境中显示)。我没有用 CDI 进行测试,但我认为 bean 的更新将在调用 getter 之后,就好像 ClassB 调用了 classA.setValX()。
-
你唯一需要做的就是在使用ClassA的属性之前绑定ClassB的任何属性