我有一些JSF页面和一些管理bean。在管理 bean 中,我创建了一些 odel 文件并尝试通过 JSF 填充它。但它不会在其中设置值。但是当我在工作中使用现有的模型对象时,效果很好。
这是我的JSF代码:
<h:form>
<c:set var="patient" value="#{manageBean.patient}" />
<p:panel id="panel" header="Patient" style="margin-bottom:10px;">
<h:panelGrid columns="2">
<h:outputLabel value="First name" />
<p:inputText id="firstName" required="true" value="#{patient.firstName}" />
<h:outputLabel value="Family name" />
<p:inputText id="familyName" required="true" value="#{patient.familyName}" />
<h:outputLabel value="Sex"/>
<p:selectOneMenu id="sex" rendered="true" value="#{patient.sex}">
<f:selectItem itemLabel="Male" itemValue="male" />
<f:selectItem itemLabel="Female" itemValue="female" />
</p:selectOneMenu>
<h:outputLabel value="Birthday date" />
<p:calendar value="#{patient.birthdayDate}" mode="inline" id="birthdayDate"/>
<h:outputLabel value="Nationality"/>
<p:selectOneMenu id="nationality" rendered="true" value="#{patient.nationality}">
<f:selectItem itemLabel="Russian" itemValue="russian" />
<f:selectItem itemLabel="Ukranian" itemValue="ukranian" />
</p:selectOneMenu>
<h:outputLabel value="Adress" />
<p:inputText id="adress" required="true" value="#{patient.adress}" />
<h:outputLabel value="Phone number" />
<p:inputMask id="phoneNumber" required="true" value="#{patient.phoneNumber}" mask="(999) 999-9999"/>
</h:panelGrid>
</p:panel>
<p:commandButton value="Save" action="#{manageBean.save}" />
</h:form>
还有我的管理豆:
@ManagedBean(name = "manageBean")
@SessionScoped
public class ManageBean implements Serializable {
private Patient patient;
private SessionFactory factory;
public ManageBean() {
factory = SessionFactoryWrap.getInstance();
}
public Patient getPatient() {
patient = (Patient) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("patient");
if (patient == null) {
//patient = new Patient("", "", Sex.male, new Date(), Nationality.ukranian, "", "");
patient = new Patient();
}
return patient;
}
public String save() {
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.saveOrUpdate(patient);
tx.commit();
} catch (HibernateException ex) {
if (tx != null) {
tx.rollback();
}
ex.printStackTrace();
} finally {
session.close();
}
patient=null;
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("patient", null);
return "go_home";
}
}
尝试更改:
<c:set var="patient" value="#{manageBean.patient}" />
自:
<ui:param name="patient" value="#{manageBean.patient}" />
这样,你把它放在一个 Facelet 变量中,你以后就可以引用它来获取和设置。
然后,将患者对象的初始化放在@PostConstruct
注释的方法中,如下所示:
@PostConstruct
public void init() {
patient = new Patient(); // this will execute every tyme the bean is initialized
}
然后只需使用普通的吸气剂和设置器(无自定义代码)来获取患者属性。
的另一种方法是根本不使用任何参数,而只是将UIInput
组件直接绑定到属性:
<h:form>
<p:panel id="panel" header="Patient" style="margin-bottom:10px;">
<h:panelGrid columns="2">
<h:outputLabel value="First name" />
<p:inputText id="firstName" required="true"
value="#{manageBean.patient.firstName}" />
<!-- rest of JSF/Facelets code... -->
</h:form>
此外,按照 JSF 最佳实践,您可以通过两种方式重新定义您的托管 Bean(据我所知 atm):
您不需要具有
@SessionScoped
注释来处理 ajax 请求,这也意味着构造函数(和@PostConstruct
方法)每个会话只会被调用一次。在这种情况下,最好的选择是@ViewScoped
注释。详细信息:托管 Bean 作用域。在 getter/setter 方法中不得有任何业务逻辑,因为它将针对 JSF 代码中的每个
#{managedBean.property}
执行,更多信息:为什么 JSF 多次调用 getter。知道了这一点,最好只在 Bean 构造函数或@PostConstruct
方法中加载一次会话数据。
有了这一切,您的托管 Bean 应如下所示:
@ManagedBean(name = "manageBean")
@ViewScoped
public class ManageBean implements Serializable {
private Patient patient;
private SessionFactory factory;
public ManageBean() {
}
@PostConstruct
public void init() {
//it would be better to initialize everything here
factory = SessionFactoryWrap.getInstance();
patient = (Patient)FacesContext.getCurrentInstance().getExternalContext().
getSessionMap().get("patient");
if (patient == null) {
patient = new Patient();
}
}
public Patient getPatient() {
return patient;
}
public void setPatient(Patient patient) {
this.patient = patient;
}
public String save() {
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.saveOrUpdate(patient);
tx.commit();
} catch (HibernateException ex) {
if (tx != null) {
tx.rollback();
}
ex.printStackTrace();
//in my opinion, it would be better to show a descriptive message
//instead of returning to the `go_home` view in case of errors.
} finally {
session.close();
}
//clumsy code line, no need to have it at all
//patient = null;
//Don't set the parameter to null, instead remove it from the session map.
FacesContext.getCurrentInstance().getExternalContext().
getSessionMap().remove("patient");
return "go_home";
}
}