Yanıtlar:
JSTL <c:xxx>
etiketlerinin tümü etiket işleyicilerdir ve görünüm oluşturma süresi boyunca yürütülürken , JSF <h:xxx>
etiketleri tüm UI bileşenleridir ve görünüm oluşturma süresi sırasında yürütülür .
Not o JSF kendi gelen <f:xxx>
ve <ui:xxx>
iciler sadece etiketleri değil uzanmaktadır UIComponent
, ayrıca taghandlers vardır mesela <f:validator>
, <ui:include>
, <ui:define>
vb uzanan olanlar UIComponent
da mesela JSF UI bileşenleri vardır <f:param>
, <ui:fragment>
, <ui:repeat>
vb MTU UI bileşenleri itibaren sadece id
ve binding
nitelikleridir ayrıca görünüm oluşturma süresi boyunca değerlendirilir. Dolayısıyla JSTL yaşam döngüsüne ilişkin aşağıdaki cevap JSF bileşenlerinin id
ve binding
öznitelikleri için de geçerlidir .
Görünüm oluşturma süresi XHTML / JSP ayrıştırılır ve daha sonra da depolanan bir MTU bileşeni ağaca dönüştürülecek olduğu an UIViewRoot
arasında FacesContext
. Görünüm oluşturma süresi, JSF bileşen ağacının HTML üretmek üzere olduğu andan itibaren başlar UIViewRoot#encodeAll()
. Yani: JSF UI bileşenleri ve JSTL etiketleri kodlamadan beklediğiniz gibi senkronize çalışmaz. Aşağıdaki gibi görselleştirebilirsiniz: JSTL önce yukarıdan aşağıya doğru çalışır ve JSF bileşen ağacını üretir, sonra JSF'nin HTML çıkışını üreterek tekrar yukarıdan aşağıya doğru sıraya girer.
<c:forEach>
vs <ui:repeat>
Örneğin, bu Facelets işaretlemesi 3 öğeden fazla yineleme kullanarak <c:forEach>
:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
... görünüm oluşturma süresi boyunca <h:outputText>
, kabaca şu şekilde temsil edilen JSF bileşen ağacında üç ayrı bileşen oluşturur :
<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}" />
... bu da görüntüleme oluşturma süresi boyunca HTML çıktılarını ayrı ayrı oluşturur:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Bileşen kimliklerinin benzersizliğini manuel olarak sağlamanız gerektiğini ve bunların görünüm oluşturma sırasında da değerlendirildiğini unutmayın.
Bu Facelets biçimlendirmesi <ui:repeat>
, bir JSF UI bileşeni olan 3 öğeden fazla yineleme yaparken :
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
... JSF bileşen ağacında olduğu gibi sonlanır ve burada aynı <h:outputText>
bileşen, görünüm yineleme süresinin geçerli yineleme turuna dayalı olarak HTML çıktısı oluşturmak için yeniden kullanılması sırasında kullanılır :
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Not olduğu <ui:repeat>
bir varlık olarak NamingContainer
bileşen zaten yineleme endeksine dayalı müşteri kimliği benzersizliğini sağlanmalıdır; Ayrıca id
, görünüm oluşturma süresi sırasında da değerlendirilirken #{item}
, yalnızca görünüm oluşturma süresi sırasında da kullanılabilir olduğundan, EL'i alt bileşenlerin niteliğinde bu şekilde kullanmak da mümkün değildir . Aynı h:dataTable
ve benzer bileşenler için de geçerlidir .
<c:if>
/ <c:choose>
vsrendered
Başka bir örnek olarak, bu Facelets biçimlendirmesi aşağıdakileri kullanarak koşullu olarak farklı etiketler ekler <c:if>
( <c:choose><c:when><c:otherwise>
bunun için de kullanabilirsiniz ):
<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>
... bileşeni type = TEXT
yalnızca <h:inputText>
JSF bileşen ağacına ekleyecekse :
<h:inputText ... />
Bu Facelets işaretlemesi olurken:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
... durumdan bağımsız olarak JSF bileşen ağacında yukarıdaki gibi sonuçlanır. Bu nedenle, birçoğuna sahip olduğunuzda "şişirilmiş" bir bileşen ağacıyla sonuçlanabilir ve bunlar aslında bir "statik" modele dayanır (yani field
en azından görünüm kapsamı sırasında hiç değişmez). Ayrıca, EL içine çalışabilir sorun Eğer 2.2.7 önce Mojarra sürümlerinde ek özelliklere sahip alt sınıfları ile anlaşma yaparken.
<c:set>
vs <ui:param>
Değiştirilemezler. <c:set>
Setleri sadece erişilebilir EL kapsamında değişken, sonra görünüm inşa süresi boyunca etiket konumu, ama hiçbir yerde görünümde görüntüleme sırasında zaman kılmak. <ui:param>
Bir Facelet şablonu için bir EL değişken ile yer geçer <ui:include>
, <ui:decorate template>
ya da <ui:composition template>
. Eski JSF sürümlerinde, <ui:param>
değişkenin söz konusu Facelet şablonunun dışında da kullanılabileceği hatalar vardı , buna asla güvenilmemelidir.
Niteliği <c:set>
olmayan scope
bir takma ad gibi davranacaktır. EL ifadesinin sonucunu hiçbir kapsamda önbelleğe almaz. Böylece örneğin JSF bileşenlerini yinelemek için mükemmel şekilde kullanılabilir. Böylece, örneğin aşağıda iyi çalışır:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
Sadece bir döngüdeki toplamı hesaplamak için uygun değildir. Bunun için EL 3.0 akışını kullanın :
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Belirlediğiniz Yalnızca, scope
izin verilen değerlerden biri ile niteliğini request
, view
, session
, veya application
, o zaman görünümü inşa süresi boyunca hemen değerlendirilir ve belirtilen kapsamda saklanacaktır.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
Bu sadece bir kez değerlendirilecek #{dev}
ve tüm başvuru boyunca olduğu gibi sağlanacaktır .
Gibi JSF ilerlerken bileşenlerin içinde kullanılan edilirken JSTL kullanılması, yalnızca beklenmedik sonuçlara yol açabilir <h:dataTable>
, <ui:repeat>
vb veya JSTL etiket nitelikleri gibi JSF olayların sonuçlarına bağlı olduğunda preRenderView
görünümü inşa süre içinde bulunmayan modelinde form değerleri veya gönderilen . Bu nedenle, JSTL etiketlerini yalnızca JSF bileşen ağacı oluşturma akışını denetlemek için kullanın. HTML çıkış oluşturma akışını kontrol etmek için JSF UI bileşenlerini kullanın. var
Yinelenen JSF bileşenlerini JSTL etiketi özniteliklerine bağlamayın . JSTL etiketi niteliklerindeki JSF olaylarına güvenmeyin.
Her zaman bir bileşeni yedekleme çekirdeğine bağlamanız binding
veya bir tane yakalamanız findComponent()
ve bir yedekleme çekirdeğinde Java kodunu kullanarak çocuklarını oluşturup / manipüle new SomeComponent()
etmeniz gerektiğini düşündüğünüzde, o zaman hemen JSTL kullanmayı bırakmalı ve kullanmayı düşünmelisiniz. JSTL ayrıca XML tabanlı olduğundan, JSF bileşenlerini dinamik olarak oluşturmak için gereken kod çok daha iyi okunabilir ve bakımı yapılabilir hale gelir.
Bilmesi gereken önemli bir nokta, 2.1.18'den daha eski Mojarra sürümlerinde, JSTL etiketi özelliğinde görünüm kapsamındaki bir çekirdeğe başvururken kısmi durum kaydetmede bir hata olmasıdır. Tüm görünüm kapsamı çekirdeği , görünüm ağacından alınmak yerine yeni olarak yeniden oluşturulacaktır (yalnızca görünüm ağacının henüz JSTL'nin çalıştığı noktada mevcut olmaması nedeniyle). Bir JSTL etiketi özniteliği tarafından görünüm kapsamındaki fasulyede bir durum bekliyorsanız veya saklıyorsanız, beklediğiniz değeri döndürmez veya görünümden sonra geri yüklenen gerçek görünüm kapsamındaki fasulyede "kaybolur" ağaç inşa edilmiştir. Mojarra 2.1.18 veya daha yeni bir sürüme geçemiyorsanız, geçici çözüm kısmi durum tasarrufunu web.xml
aşağıdaki gibi kapatmaktır :
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
@ViewScoped
etiket işleyicilerinde başarısızJSTL etiketlerinin yararlı olduğu bazı gerçek dünya örneklerini görmek için (örneğin, görünüm oluştururken gerçekten doğru bir şekilde kullanıldığında), aşağıdaki sorulara / cevaplara bakın:
Somut işlevsel gereksiniminizle ilgili olarak, JSF bileşenlerini koşullu olarak oluşturmak istiyorsanız , rendered
bunun yerine JSF HTML bileşenindeki özniteliği kullanın, özellikle veya #{lpc}
gibi bir JSF yineleme bileşeninin şu anda yinelenen öğesini temsil ediyorsa .<h:dataTable>
<ui:repeat>
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Veya koşullu olarak JSF bileşenleri oluşturmak (oluşturmak / eklemek) istiyorsanız , JSTL kullanmaya devam edin. Java'da ayrıntılı olarak yapmaktan çok daha iyi new SomeComponent()
.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
<ui:repeat>
, bir etiket işleyicisi olan izlenim içindeyim (bu satırdan dolayı, " JSF'nin kendisinin <f:xxx>
ve <ui:xxx>
... " olduğunu unutmayın) <c:forEach>
ve bu nedenle, görünüm oluşturma zamanında değerlendirilir (yine aynı gibi <c:forEach>
) . Eğer öyleyse, <ui:repeat>
ve <c:forEach>
? Arasında görünür, işlevsel bir fark olmamalıdır. Bu paragrafın tam olarak ne anlama geldiğini anlamıyorum :)
<f:xxx>
ve <ui:xxx>
uzatmaz etiketleri UIComponent
de etiket işleyicileri vardır. " İma etmek girişimleri <ui:repeat>
nedeniyle de bir etiket işleyicisi olan <ui:xxx>
da kapsar <ui:repeat>
? Bu daha sonra bunun <ui:repeat>
, <ui:xxx>
uzayan bileşenlerden biri olduğu anlamına gelmelidir UIComponent
. Bu nedenle, bir etiket işleyici değildir. (Bazıları uzanmayabilir UIComponent
. Bu nedenle, etiket işleyicisidir) Öyle mi?
<c:set>
without scope
, değerlendirilen değeri hedef kapsamda ayarlamak yerine EL ifadesinin bir takma adını oluşturur. Deneyin scope="request"
hemen (aslında görünüm oluşturma süresi boyunca) değerini değerlendirmek, hangi yerine ve (yineleme sırasında "üzerine yazılır" olmayacak olan) istek niteliği olarak ayarlayın. Kapakların altında bir ValueExpression
nesne oluşturur ve ayarlar .
ClassNotFoundException
. Projenizin çalışma zamanı bağımlılıkları bozuldu. Büyük olasılıkla Tomcat gibi JavaEE olmayan bir sunucu kullanıyorsunuz ve JSTL'yi yüklemeyi unuttunuz veya yanlışlıkla JSTL 1.0 ve JSTL 1.1+ sürümlerini dahil ettiniz. Çünkü JSTL 1.0'da paket javax.servlet.jstl.core.*
ve JSTL 1.1'den beri bu olmuştur javax.servlet.jsp.jstl.core.*
.
kullanım
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
Anahtar benzeri çıkış için, PrimeFaces Uzantılarından anahtar yüzünü kullanabilirsiniz .