Jsf2 Facelets JSTL... mantıklı?

şartlı olarak biraz Faselet kodu çıkarmak istiyorum.

bu amaçla, jstl etiketleri iyi çalışıyor gibi görünüyor:

<c:if test="${lpc.verbose}">
    ...
</c:if>

Bununla birlikte, bunun en iyi uygulama olup olmadığından emin değilim? Amacıma ulaşmanın başka bir yolu var mı?

149
tarihinde sordu BalusC 2010-07-27 15:11:36
kaynak

3 ответов

giriş

jstl <c:xxx> etiketlerinin hepsi taghandlers ve görünüm oluşturma süresi sırasında yürütülür, JSF <h:xxx> etiketlerinin hepsi UI bileşenleri sırasında yürütülür ve görünüm oluşturma süresi sırasında yürütülür .

JSF'NİN kendi <f:xxx> ve <ui:xxx> etiketlerinden yalnızca yapanlara dikkat edin. UIComponent dan uzatın da taghandlers, örn. <f:validator> , <ui:include> , <ui:define> , vb. UIComponent dan uzanan olanlar da JSF UI bileşenleri, örn. <f:param> , <ui:fragment> , <ui:repeat> , vb. JSF UI bileşenlerinden yalnızca id ve binding öznitelikleri görünüm oluşturma süresi sırasında da değerlendirilir. Böylece JSTL yaşam döngüsüne ilişkin aşağıdaki cevap da id ve binding için geçerlidir JSF bileşenlerinin öznitelikleri.

XHTML/JSP dosyasının ayrıştırılması ve daha sonra UIViewRoot FacesContext olarak saklanan bir JSF bileşen ağacına dönüştürülmesi o an görünüm oluşturma zamanı . Görünüm oluşturma süresi, JSF bileşen ağacının UIViewRoot#encodeAll() ile başlayarak HTML oluşturmak üzere olduğu andır . Yani: JSF UI bileşenleri ve jstl etiketleri kodlamadan beklediğiniz gibi senkronize çalışmaz. Bunu aşağıdaki gibi görselleştirebilirsiniz: jstl yukarıdan aşağıya doğru çalışır ilk önce, JSF bileşen ağacını üreten, daha sonra JSF'NİN HTML çıktısını üreten yukarıdan aşağıya doğru tekrar çalışma sırası.

<c:forEach> vs <ui:repeat>

örneğin, <c:forEach> kullanarak 3 öğe üzerinde yineleme bu Facelets biçimlendirme:

<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 sırasında üç ayrı oluşturur <h:outputText> JSF bileşen ağacındaki bileşenler, kabaca şu şekilde temsil edilir:

<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ünüm oluşturma süresi sırasında HTML çıktılarını ayrı ayrı üretir:

<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>

, bileşen kimliklerinin benzersizliğini el ile sağlamanız gerektiğini ve bunların görünüm oluşturma süresi boyunca da değerlendirildiğini unutmayın.

bu Facelets biçimlendirme <ui:repeat> kullanarak 3 öğe üzerinde yineleme yaparken, bir JSF UI bileşeni olan:

<ui:repeat id="items" value="#{bean.items}" var="item">
    <h:outputText id="item" value="#{item.value}" />
</ui:repeat>

...zaten jsf'de olduğu gibi biter bileşen ağacı, aynı <h:outputText> bileşeni, görüntüleme sırasında, 1519880920 'olarak yeniden kullanılır , mevcut yineleme turuna göre HTML çıktısını oluşturmak için:

<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>

, <ui:repeat> bileşeninin NamingContainer bileşeninin, yineleme endeksine dayalı olarak istemci kimliğinin benzersizliğini sağladığını unutmayın; id alt bileşenlerin özniteliğinde, görünüm sırasında da değerlendirildiği için bu şekilde kullanmak da mümkün değildir #{item} yalnızca görünüm oluşturma süresi sırasında kullanılabilirken zaman oluşturun. Aynı h:dataTable ve benzeri bileşenler için de geçerlidir.

<c:if> / <c:choose> vs rendered

başka bir örnek olarak, bu Faselets koşullu olarak <c:if> kullanarak farklı etiketler ekleme (bunun için <c:choose><c:when><c:otherwise> 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>

... type = TEXT durumunda sadece <h:inputText> bileşenini ekleyecektir JSF bileşen ağacına:

<h:inputText ... />

bu Facelets işaretleme ise:

<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />

...koşul ne olursa olsun JSF bileşen ağacında tam olarak yukarıda olduğu gibi sona erecek. Bu, birçoğunuz olduğunda ve aslında "statik" bir modele dayandığında (yani field en azından görünüm kapsamı sırasında değişmez) "şişirilmiş" bir bileşen ağacına neden olabilir. Ayrıca, sorun içine çalıştırabilirsiniz 2.2.7'den önce Mojarra sürümlerinde ek özelliklere sahip alt sınıflarla uğraştığınızda.

<c:set> vs <ui:param>

onlar değiştirilebilir değildir. <c:set> , yalnızca sonra görünüm oluşturma süresi sırasında etiket konumu, ancak görünüm oluşturma süresi sırasında görünümdeki herhangi bir yerde erişilebilen EL kapsamında bir değişken ayarlar. <ui:param> , bir el değişkenini bir Faselet şablonuna geçirir. <ui:include> , <ui:decorate template> veya <ui:composition template> . Eski JSF sürümleri, <ui:param> değişkeninin söz konusu Facelet şablonunun dışında da mevcut olduğu hatalara sahipti, bu asla güvenilmemelidir.

bir scope özniteliği olmayan <c:set> bir takma ad gibi davranacaktır. EL ifadesinin sonucunu herhangi bir kapsamda önbelleğe almaz. Bu nedenle, örneğin JSF bileşenlerini yinelemek için mükemmel bir şekilde kullanılabilir. Böylece, örneğin aşağıda iyi çalışacaktı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üde toplamı hesaplamak için uygun değildir. Bunun yerine el 3.0 akışı kullanın:

<ui:repeat value="#{bean.products}" var="product">
    ...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>

yalnızca, scope özniteliğini izin verilen değerlerden biriyle ayarladığınızda request , view , session , veya application , daha sonra Görünüm oluşturma süresi sırasında hemen değerlendirilir ve belirtilen kapsamda saklanır.

<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />

bu sadece bir kez değerlendirilir ve tüm uygulama boyunca #{dev} olarak kullanılabilir olacaktır.

JSF bileşen ağaç yapısını kontrol etmek için Jstl kullanın

Jstl kullanarak yalnızca <h:dataTable> , <ui:repeat> , vb. gibi JSF yineleme bileşenleri içinde kullanılırken veya JSTL etiket özniteliklerinin preRenderView gibi JSF olaylarının sonuçlarına veya preRenderView olmayan modelde gönderilen form değerlerine bağlı olması durumunda beklenmeyen sonuçlara yol açabilir görünüm oluşturma süresi sırasında kullanılabilir. Bu nedenle, JSF bileşen ağaç yapısının akışını kontrol etmek için yalnızca JSTL etiketlerini kullanın. HTML çıkış üretimi akışını kontrol etmek için JSF UI bileşenleri kullanın. JSF bileşenlerini jstl etiket özniteliklerine yineleyen var bağlamayın. JSTL etiket özniteliklerinde JSF olaylarına güvenmeyin.

her zaman binding aracılığıyla destek fasulye bir bileşeni bağlamak veya findComponent() üzerinden bir kapmak ve oluşturmak/Java kullanarak çocuklarını işlemek gerektiğini düşünüyorum new SomeComponent() ve ne değil ile bir destek fasulye kodu, o zaman hemen durdurmak ve bunun yerine jstl kullanmayı düşünmelisiniz. JSTL ayrıca XML tabanlı olduğu için, JSF bileşenlerini dinamik olarak oluşturmak için gereken kod çok daha iyi okunabilir ve sürdürülebilir hale gelecektir.

bilmek önemlidir, 2.1.18'den eski mojarra sürümlerinin bir jstl etiket özniteliğinde bir görünüm scoped bean başvururken kısmi durumda bir hata oluşturmasıdır. Tüm görünüm scoped fasulye olurdu. , görünüm ağacından alınmak yerine yeniden oluşturuldu (sadece tam görünüm ağacının jstl çalıştığı noktada henüz mevcut olmadığı için). Bir jstl etiketi özniteliği tarafından scoped bean görünümünde bir durumu bekliyorsanız veya saklıyorsanız, beklediğiniz değeri döndürmez veya Görünüm ağacı oluşturulduktan sonra geri yüklenen gerçek görünüm scoped bean'da "kaybolur". Mojarra 2.1.18 veya daha yeni sürümüne yükseltilemiyorsanız, çalışma, kısmi durum tasarrufunu kapatmaktır web.xml aşağıdaki gibi:

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>

Ayrıca bakınız:

jstl etiketlerinin yararlı olduğu bazı gerçek dünya örneklerini görmek için (yani görünümü oluştururken gerçekten düzgün bir şekilde kullanıldığında), aşağıdaki sorulara/cevaplara bakın:


özetle

JSF bileşenlerini koşullu olarak işlemek istiyorsanız, rendered özniteliğini JSF HTML bileşeninde kullanın., , , #{lpc} , <h:dataTable> veya <ui:repeat> gibi bir JSF yineleme bileşeninin şu anda yinelenmiş öğesini temsil ediyorsa .

<h:someComponent rendered="#{lpc.verbose}">
    ...
</h:someComponent>

veya build (oluşturma/ekleme) JSF bileşenleri koşullu olarak istiyorsanız, jstl kullanmaya devam edin. Java'da new SomeComponent() yapmaktan çok daha iyi.

<c:if test="#{lpc.verbose}">
    <h:someComponent>
        ...
    </h:someComponent>
</c:if>

Ayrıca bakınız:

287
cevap BalusC 2018-03-13 20:15:55
kaynak

kullanım

<h:panelGroup rendered="#{lpc.verbose}">
  ...
</h:panelGroup>
12
cevap Bozho 2015-05-27 10:47:03
kaynak

ayrı cevap için üzgünüm, ancak yukarıdaki cevapları yorumlayamadım.

anahtar benzeri çıktı için primefaces-extensions dan anahtarı kullanabilirsiniz .

4
cevap Ravshan Samandarov 2016-08-25 12:58:47
kaynak

Diğer sorular jsf-2 jstl jsf facelets