2010-02-16 8 views
5

मैं इन दिनों जेएसएफ + फेसलेट्स के बारे में काम कर रहा हूं और सीख रहा हूं। मेरे पास बैकिंगबीन और फेसलेट एक्सएचटीएमएल पेज है। जब मैं फेसलेट पेज (केवल एक बार) का अनुरोध करता हूं तो बैकिंग-बीन-विधि को कई बार कहा जाता है।फेसलेट का अनुरोध करते समय बैकिंगबीन विधि को कई बार क्यों कहा जाता है?

इसका कारण क्या हो सकता है?

मैं कुछ खास नहीं देख सकता। अग्रिम में धन्यवाद। यहाँ

<?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> 

और समर्थन बीन है:

यहाँ facelet है। विधि 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; 
    } 

} 
+0

क्या इसे हमेशा एक ही संख्या कहा जाता है? – volvox

+0

क्या आप कई बार बुलाए गए तरीकों को सत्यापित करने के लिए अपने आईडीई डीबग मोड का उपयोग करते हैं या आप इसे लॉग में देखते हैं? – Roman

+0

ऐसा लगता है कि पहले अनुरोध पर इसे 8 बार कहा जाता है और इसके बाद इसे 21 बार कहा जाता है।मैं ग्रहण + ग्लासफ़िश का उपयोग करता हूं और इसे डीबग मोड में शुरू करता हूं। मैंने बस विधि में एक sysout डाला और कंसोल आउटपुट गिना। – c0d3x

उत्तर

8

एक बीन के प्राप्तकर्ता पर पहुंच दृश्य पक्ष से मॉडल डेटा तक पहुंचते हैं। उन्हें कई बार बुलाया जा सकता है। आम तौर पर एक या दो बार, लेकिन यह सैकड़ों बार तक बढ़ सकता है, खासकर जब UIData घटकों या value (rendered, disabled, आदि) से अन्य विशेषताओं में भी उपयोग किया जाता है। यह आम तौर पर नुकसान नहीं पहुंचाता है, क्योंकि यह एक साधारण विधि-आमंत्रण है और महंगा डेटा लोडिंग तर्क या गणना करना आमतौर पर गेटर्स में नहीं किया जाता है। प्रीलोडिंग/प्रारंभिक आमतौर पर बीन कन्स्ट्रक्टर और/या बीन एक्शन विधियों में किया जाना है। गेटर्स वास्तव में केवल डेटा डेटा (यदि आवश्यक हो तो आलसी लोडिंग) चाहिए।

getApplication().getKunden(getNameFilterPattern()); एक बहुत महंगा काम कर रहा है, तो आप वास्तव में यह या तो सेम निर्माता, या सेम @PostConstruct विधि, या सेम प्रारंभ ब्लॉक, या सेम कार्रवाई विधि के लिए ले जाते हैं, या गेटर में परिचय आलसी लोड हो रहा है पैटर्न चाहिए। यहाँ एक उदाहरण से पता चलता है जो कैसे करना है यह सब:

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 अनुरोध पैरामीटर से प्राप्त किया जा करने के लिए है अगर) (यदि nameFilterPatternPOST फॉर्म इनपुट फ़ील्ड से प्राप्त किया जाना है) उपयुक्त है।

जेएसएफ जीवन चक्र के बारे में और जानने के लिए, आपको यह self-practice article उपयोगी मिल सकता है।

+0

अच्छा जवाब है, btw :) http://stackoverflow.com/questions/2090033/why-jsf-calls-getters-multiple-times – ewernli

+0

हाँ, यह निश्चित रूप से नहीं पहली बार मैं ऐसे ही जवाब है :) मैं इसे aswered गए कम से कम 20 बार पहले। न केवल यहां, बल्कि forums.sun.com और इसी तरह भी। – BalusC

2

यह JSF lifecylce के विभिन्न phases से कहा जा सकता है। मेरी शर्त चरण RestoreView और फिर RenderResponse होगी - मैं हाल ही में जेएसएफ का उपयोग नहीं कर रहा हूं, इसलिए मुझे इसे विस्तार से याद नहीं है।

आप नवीनतम फ़िल्टर पैटर्न और संबंधित ग्राहकों को कैश कर सकते हैं। फ़िल्टर को बदलते समय आप केवल क्लाइंट को पुनः लोड करते हैं। इस तरह, आप इस विशेष समस्या को हल करते हैं, साथ ही अगर फ़िल्टर नहीं बदला जाता है तो डेटा को पुनः लोड करने से बचें।

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 के बजाय) का उपयोग करें और सुनिश्चित करें कि आप अनुरोध के अनुसार केवल एक बार डेटा लोड कर सकते हैं।

+0

उत्तर देने के लिए धन्यवाद। मैंने दायरे का अनुरोध करने के लिए बीन बदल दिया। व्यवहार वही है। मैं केवल प्रति अनुरोध केवल डेटा लोड करने के लिए सुनिश्चित कर सकता हूं? जैसा कि आप फेसलेट में देख सकते हैं, विधि केवल एक बार संदर्भित है। क्या यह टेम्पलेट सामग्री से संबंधित हो सकता है: ui: संरचना/ui: परिभाषित करें? – c0d3x

+0

आपके द्वारा स्वीकार किए गए बलससी का उत्तर यह सब शामिल है। मुझे लगता है कि आपको और स्पष्टीकरण की आवश्यकता नहीं है। – ewernli

संबंधित मुद्दे