जवाबों:
JSTL <c:xxx>
टैग सभी टैगहैंडलर हैं और इन्हें व्यू बिल्ड टाइम के दौरान निष्पादित किया जाता है , जबकि JSF <h:xxx>
टैग सभी UI घटक होते हैं और इन्हें व्यू रेंडर समय के दौरान निष्पादित किया जाता है ।
ध्यान दें कि JSF के स्वयं से <f:xxx>
और <ui:xxx>
उन जो करते टैग सिर्फ़ नहीं से विस्तार UIComponent
, भी taghandlers हैं जैसे <f:validator>
, <ui:include>
, <ui:define>
, आदि लोगों से दूर का विस्तार UIComponent
भी JSF UI घटक, जैसे हैं <f:param>
, <ui:fragment>
, <ui:repeat>
, आदि JSF UI घटक से केवल id
और binding
गुण हैं निर्माण समय देखने के दौरान भी मूल्यांकन किया गया। इस प्रकार जेएसटीएल जीवनचक्र के नीचे दिए गए उत्तर भी जेएसएफ घटकों की विशेषताओं id
और binding
विशेषताओं पर लागू होते हैं।
व्यू बिल्ड टाइम वह पल होता है जब XHTML / JSP फाइल को जेएसएफ कंपोनेंट ट्री में पार्स और कन्वर्ट करना होता है जिसे बाद में स्टोर किया जाता UIViewRoot
है FacesContext
। दृश्य प्रस्तुत करने का समय वह क्षण होता है जब JSF घटक ट्री HTML उत्पन्न करने वाला होता है, जिसके साथ शुरू होता हैUIViewRoot#encodeAll()
। तो: JSF UI घटक और JSTL टैग सिंक में नहीं चलते हैं जैसा कि आप कोडिंग से उम्मीद करेंगे। आप इसे निम्नानुसार कल्पना कर सकते हैं: जेएसटीएल ऊपर से नीचे तक चलता है, जेएसएफ घटक पेड़ का उत्पादन करता है, फिर यह जेएसएफ की बारी है ऊपर से नीचे तक फिर से चलाने के लिए, HTML आउटपुट का उत्पादन।
<c:forEach>
बनाम <ui:repeat>
उदाहरण के लिए, इस फेसलेट्स का उपयोग करके 3 से अधिक आइटम्स को चिह्नित करना है <c:forEach>
:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
... <h:outputText>
जेएसएफ घटक के पेड़ में तीन अलग-अलग घटकों को देखने के समय के दौरान बनाता है , मोटे तौर पर इस तरह का प्रतिनिधित्व किया:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
... जो बदले में समय प्रस्तुत करने के दौरान व्यक्तिगत रूप से अपने HTML आउटपुट उत्पन्न करते हैं:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
ध्यान दें कि आपको घटक आईडी की विशिष्टता को मैन्युअल रूप से सुनिश्चित करने की आवश्यकता है और यह भी कि व्यू बिल्ड समय के दौरान उनका मूल्यांकन किया जाता है।
जबकि इस फेसलेट्स का उपयोग करते हुए 3 से अधिक आइटम्स को चिह्नित करना है <ui:repeat>
, जो कि JSF UI घटक है:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
... पहले से ही जेएसएफ घटक के पेड़ के रूप में समाप्त होता है, जिसके कारण बहुत ही <h:outputText>
घटक दृश्य रेंडर समय वर्तमान पुनरावृत्ति दौर के आधार पर HTML उत्पादन उत्पन्न करने के लिए पुन: उपयोग किया जा रहा है :
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
ध्यान दें कि <ui:repeat>
एक NamingContainer
घटक होने के नाते पहले से ही पुनरावृत्ति सूचकांक के आधार पर क्लाइंट आईडी की विशिष्टता सुनिश्चित की गई थी; id
इस तरह से बाल घटकों की विशेषता में ईएल का उपयोग करना भी संभव नहीं है क्योंकि यह दृश्य निर्माण समय के दौरान भी मूल्यांकन किया #{item}
जाता है जबकि केवल दृश्य रेंडर समय के दौरान उपलब्ध है। समान h:dataTable
और समान घटकों के लिए समान है।
<c:if>
/ <c:choose>
बनामrendered
एक अन्य उदाहरण के रूप में, यह फ़ेसलेट सशर्त रूप से अलग-अलग टैग का उपयोग करके जोड़ रहा है <c:if>
(आप इसके लिए भी उपयोग कर सकते हैं <c:choose><c:when><c:otherwise>
):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
... type = TEXT
केवल <h:inputText>
JSF घटक ट्री में घटक जोड़ने के मामले में :
<h:inputText ... />
जबकि यह फेसलेट्स मार्कअप:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
... शर्त की परवाह किए बिना JSF घटक के पेड़ में ऊपर के रूप में बिल्कुल खत्म हो जाएगा। यह इस प्रकार एक "फूला हुआ" घटक वृक्ष में समाप्त हो सकता है जब आपके पास उनमें से कई होते हैं और वे वास्तव में एक "स्थिर" मॉडल पर आधारित होते हैं (यानी field
कम से कम दृश्य गुंजाइश के दौरान कभी नहीं बदलता है)। जब आप 2.2.7 से पहले मोजरा संस्करणों में अतिरिक्त गुणों के साथ सौदा करते हैं, तो आप ईएल मुसीबत में भाग सकते हैं ।
<c:set>
बनाम <ui:param>
वे विनिमेय नहीं हैं। <c:set>
सेट ईएल दायरे में एक चर, जो केवल पहुँचा जा सकता है के बाद दृश्य का निर्माण समय के दौरान टैग, लेकिन दृश्य में कहीं भी देखने के दौरान समय प्रस्तुत करना। <ui:param>
गुजरता एक Facelet टेम्पलेट के लिए एक ईएल चर के माध्यम से शामिल <ui:include>
, <ui:decorate template>
, या <ui:composition template>
। जेएसएफ के पुराने संस्करणों में बग थे, जिससे <ui:param>
फेसलेट टेम्पलेट के बाहर चर भी उपलब्ध है, इस पर कभी भरोसा नहीं करना चाहिए।
<c:set>
एक के बिना scope
विशेषता एक उपनाम की तरह व्यवहार करेगा। यह किसी भी दायरे में ईएल अभिव्यक्ति के परिणाम को कैश नहीं करता है। इस प्रकार जेएसएफ घटकों को पुनरावृत्त करने वाले उदाहरण के लिए इसका पूरी तरह से उपयोग किया जा सकता है। इस प्रकार, जैसे नीचे ठीक काम करेगा:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
यह केवल एक लूप में राशि की गणना के लिए उपयुक्त नहीं है। इसके बजाय EL 3.0 स्ट्रीम का उपयोग करें :
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
केवल, जब आप सेट scope
स्वीकार्य मानों में से एक के साथ विशेषता request
, view
, session
, या application
, तो यह तुरंत दृश्य का निर्माण समय के दौरान मूल्यांकन किया है और निर्दिष्ट दायरे में संग्रहीत किया जाएगा।
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
यह केवल एक बार मूल्यांकन किया जाएगा और #{dev}
पूरे आवेदन के दौरान उपलब्ध होगा।
JSTL का उपयोग केवल अप्रत्याशित परिणाम को जन्म दे सकती है जब इस तरह के रूप JSF बार-बार दोहराना घटकों के अंदर इस्तेमाल किया जा रहा <h:dataTable>
, <ui:repeat>
, आदि, या JSTL टैग विशेषताओं जैसे JSF घटनाओं के परिणामों पर निर्भर जब preRenderView
या प्रस्तुत जो दृश्य का निर्माण समय के दौरान उपलब्ध नहीं हैं मॉडल में प्रपत्र मूल्यों । इसलिए, JSTL टैग का उपयोग केवल JSF घटक ट्री बिल्डिंग के प्रवाह को नियंत्रित करने के लिए करें। HTML उत्पादन पीढ़ी के प्रवाह को नियंत्रित करने के लिए JSF UI घटकों का उपयोग करें। var
JFL टैग विशेषताओं के लिए JSF घटकों की पुनरावृति के लिए बाध्य न करें । JSTL टैग विशेषताओं में JSF घटनाओं पर भरोसा न करें।
कभी भी आपको लगता है कि आपको बैकिंग बीन के लिए एक घटक को बांधने की ज़रूरत है binding
, या एक के माध्यम से पकड़ो findComponent()
, और अपने बच्चों के साथ एक बैकिंग बीन में जावा कोड का उपयोग करके अपने बच्चों को बनाने या हेरफेर new SomeComponent()
करने की ज़रूरत है, तो आपको तुरंत रोकना चाहिए और इसके बजाय जेएसटी का उपयोग करने पर विचार करना चाहिए। जैसा कि JSTL भी XML आधारित है, JSF घटकों को गतिशील रूप से बनाने के लिए आवश्यक कोड इतना बेहतर पठनीय और बनाए रखने योग्य हो जाएगा।
यह जानना महत्वपूर्ण है कि 2.1.18 से अधिक पुराने मोजरा संस्करणों को JSTL टैग विशेषता में देखने वाले बीन बीन का संदर्भ देते समय आंशिक रूप से सहेजने में एक बग था। पूरे दृश्य को काटे हुए बीन को व्यू ट्री से पुनर्प्राप्त करने के बजाय नया बनाया जाएगा (केवल इसलिए कि पूरा दृश्य ट्री अभी तक JSTL रन पर उपलब्ध नहीं है)। यदि आप किसी JSTL टैग विशेषता द्वारा सेम बीन वाले दृश्य में कुछ राज्य की अपेक्षा या भंडारण कर रहे हैं, तो यह आपके द्वारा अपेक्षित मूल्य को वापस नहीं करेगा, या यह वास्तविक दृश्य में खोई हुई बीन में "खो" जाएगा जो दृश्य के बाद पुनर्स्थापित हो जाता है पेड़ बनाया गया है। यदि आप Mojarra 2.1.18 या नए में अपग्रेड नहीं कर सकते हैं, तो web.xml
नीचे दिए गए आंशिक राज्य बचत को बंद करना है :
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
@ViewScoped
टैग हैंडलर में विफल रहता हैकुछ वास्तविक दुनिया उदाहरणों को देखने के लिए जहां JSTL टैग सहायक होते हैं (यानी जब दृश्य के निर्माण के दौरान इसका सही उपयोग किया जाता है), तो निम्न प्रश्न देखें:
अपनी ठोस कार्यात्मक आवश्यकता के अनुसार, यदि आप JSF घटकों को सशर्त रूप से प्रस्तुत करना चाहते हैं, तो rendered
इसके बजाय JSF HTML घटक पर विशेषता का उपयोग करें , विशेष रूप से यदि #{lpc}
वर्तमान में JSF पुनरावृत्त घटक जैसे <h:dataTable>
या के रूप में प्रदर्शित आइटम का प्रतिनिधित्व करता है <ui:repeat>
।
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
या, यदि आप सशर्त रूप से JSF घटकों को बनाना (बनाना / जोड़ना) चाहते हैं, तो JSTL का उपयोग करते रहें। यह new SomeComponent()
जावा में क्रिया करने की तुलना में बहुत बेहतर है ।
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
<ui:repeat>
एक टैग हैंडलर है (इस लाइन के कारण, " ध्यान दें कि JSF का अपना <f:xxx>
और <ui:xxx>
... ") केवल पसंद है <c:forEach>
और इसलिए, इसका मूल्यांकन बिल्ड टाइम (फिर से बस की तरह <c:forEach>
) पर किया जाता है । यदि ऐसा है, तो, के बीच कोई दृश्यमान, कार्यात्मक अंतर नहीं होना चाहिए <ui:repeat>
और <c:forEach>
? मुझे नहीं मिलता है कि वास्तव में उस अनुच्छेद का क्या मतलब है :)
<f:xxx>
और <ui:xxx>
टैग जो विस्तारित नहीं UIComponent
होते हैं; टैग हैंडलर हैं। " इसका अर्थ यह <ui:repeat>
है कि टैग हैंडलर <ui:xxx>
भी शामिल है क्योंकि इसमें भी शामिल हैं <ui:repeat>
? यह तो मतलब यह होना चाहिए कि <ui:repeat>
घटकों में से एक है <ui:xxx>
कि फैली हुई है UIComponent
। इसलिए, यह एक टैग हैंडलर नहीं है। (उनमें से कुछ का विस्तार नहीं हो सकता है UIComponent
। इसलिए, वे टैग हैंडलर हैं) क्या यह है?
<c:set>
नहीं scope
बनाता है। scope="request"
इसके बजाय कोशिश करें , जो तुरंत मूल्य का मूल्यांकन करेंगे (वास्तव में निर्माण समय देखें) और इसे अनुरोध विशेषता के रूप में सेट करें (जो पुनरावृत्ति के दौरान "ओवरराइट" नहीं होगा)। कवर के तहत, यह एक ValueExpression
ऑब्जेक्ट बनाता है और सेट करता है।
ClassNotFoundException
। आपकी परियोजना की रनटाइम निर्भरताएं टूट गई हैं। सबसे अधिक संभावना है कि आप गैर-जावाईई सर्वर का उपयोग कर रहे हैं जैसे कि टॉमकैट और आप जेएसटीएल को स्थापित करना भूल गए, या आपने गलती से जेएसटीएल 1.0 और जेएसटीएल 1.1+ दोनों को शामिल किया है। क्योंकि JSTL 1.0 में पैकेज है javax.servlet.jstl.core.*
और JSTL 1.1 के बाद से यह बन गया है javax.servlet.jsp.jstl.core.*
। JSTL को स्थापित करने के लिए सुराग यहां देखे जा सकते हैं: stackoverflow.com/a/4928309
उपयोग
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
स्विच-जैसे आउटपुट के लिए, आप प्राइमफेस एक्सटेंशन से स्विच फेस का उपयोग कर सकते हैं ।