لماذا تسمى طريقة BackingBean عدة مرات عند طلب Facelet؟
سؤال
أنا أعمل وأتعلم عن JSF + Facelets هذه الأيام. لديّ packingbean و page achtml facelet. عندما أطلب صفحة الوجه (مرة واحدة فقط) ، يتم استدعاء طريقة دعم التراجع عدة مرات.
ما هو السبب المتوقع لذلك؟
لا أستطيع رؤية أي شيء مميز. شكرا لك مقدما.
ها هو الوجه:
<?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:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<ui:composition template="index.xhtml">
<ui:define name="content">
<h:form>Name: <h:inputText id="nameFilterPattern" value="#{kundenBackingBean.nameFilterPattern}" /><h:commandButton value="Suchen"/></h:form>
<h:dataTable var="kunde" value="#{kundenBackingBean.kunden}" rowClasses="rowHighlight, rowOrdinary">
<h:column>
<f:facet name="header">
<h:outputText value="Kundennr" />
</f:facet>
<h:outputText value="#{kunde.kundenNr}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{kunde.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Vorname" />
</f:facet>
<h:outputText value="#{kunde.vorname}"/>
</h:column>
<h:column>
<h:outputLink>Details</h:outputLink>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
</body>
</html>
وهنا هو الدعم. تسمى طريقة getKunden عدة مرات:
@ManagedBean
@SessionScoped
public class KundenBackingBean extends AbstractBackingBean {
private String nameFilterPattern;
public List<Kunde> getKunden(){
System.out.println("getKunden");
return getApplication().getKunden(getNameFilterPattern());
}
public String getNameFilterPattern() {
return nameFilterPattern;
}
public void setNameFilterPattern(String nameFilterPattern) {
System.out.println("Name filter: " + nameFilterPattern);
this.nameFilterPattern = nameFilterPattern;
}
}
المحلول
هناك فقط من الفاصوليا هناك فقط ل التمكن من نموذج البيانات من جانب العرض. يمكن استدعاؤها عدة مرات. عادة مرتين أو مرتين ، ولكن هذا يمكن أن ينمو إلى مئات المرات ، خاصة عند استخدامه أيضًا UIData
المكونات أو في سمات أخرى من value
(مثل rendered
, disabled
, ، إلخ). هذا عادة لا يضر ، لأنه مجرد تحديد طريقة بسيطة والقيام بمنطق تحميل البيانات باهظ الثمن أو لا يجب القيام به في getters. عادة ما يتم التحميل المسبق/التهيئة في طرق عمل الفول و/أو الفول. يجب على getters في الواقع فقط إرجاع البيانات (إذا لزم الأمر أيضًا تحميل كسول).
لو getApplication().getKunden(getNameFilterPattern());
تقوم بمهمة مكلفة للغاية ، يجب عليك حقًا نقلها إلى مُنشئ الفول ، أو الفول @PostConstruct
الطريقة ، أو كتلة تهيئة الفول ، أو طريقة عمل الفول ، أو تقديم تحميل كسول نمط في getter. إليك مثال يوضح كيفية القيام بذلك:
public class Bean {
private String nameFilterPattern;
private List<Kunde> kunden;
// Load during bean construction.
public Bean() {
this.kunden = getApplication().getKunden(getNameFilterPattern());
}
// OR load during @PostConstruct (will be invoked AFTER construction and resource injection.
@PostConstruct
public void init() {
this.kunden = getApplication().getKunden(getNameFilterPattern());
}
// OR during bean initialization (this is invoked BEFORE construction and will apply to ALL constructors).
{
this.kunden = getApplication().getKunden(getNameFilterPattern());
}
// OR during bean action method (invoked from h:commandLink/Button).
public String submit() {
this.kunden = getApplication().getKunden(getNameFilterPattern());
return "navigationCaseOutcome";
}
// OR using lazy loading pattern in getter method.
public List<Kunde> getKunden() {
if (this.kunden == null)
this.kunden = getApplication().getKunden(getNameFilterPattern());
}
return this.kunden;
}
في حالتك المحددة ، أعتقد أنها @PostConstruct
(إذا nameFilterPattern
يتم الحصول عليها من أ GET
طلب المعلمة) ، أو مجرد طريقة عمل الفول (إذا nameFilterPattern
يتم الحصول عليها من أ POST
حقل الإدخال النموذج) مناسب.
لمعرفة المزيد حول دورة حياة JSF ، قد تجد هذا مقالة الممارسة الذاتية مفيد.
نصائح أخرى
يمكن استدعاؤه من مختلف المراحل من JSF Lifecylce. رهاني سيكون المراحل RestoreView
وثم RenderResponse
- لم أستخدم JSF مؤخرًا ، لذلك لا أتذكر هذا بالتفصيل.
يمكنك ذاكرة التخزين المؤقت لأحدث نمط مرشح والعملاء المقابل. يمكنك إعادة تحميل العملاء فقط إذا تغير المرشح. وبهذه الطريقة ، يمكنك حل هذه المشكلة بالذات ، بالإضافة إلى تجنب إعادة تحميل البيانات إذا لم يتغير المرشح.
private String nameFilterPattern;
private String lastNameFilterPatternLoaded;
private List<Kunde> clients;
public List<Kunde> getKunden(){
System.out.println("getKunden");
if( nameFilterPattern.equals( lastNameFilterPatternLoaded ) )
{
clients = getApplication().getKunden(getNameFilterPattern());
lastNameFilterPatternLoaded = nameFilterPattern
}
return clients;
}
أو يمكنك استخدام أ request
فول (بدلا من session
) وتأكد من تحميل البيانات مرة واحدة فقط لكل طلب.