답변:
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
속성이 있습니다 또한 뷰 빌드 시간 동안 평가되었습니다. 따라서 JSTL 라이프 사이클에 대한 아래 답변 은 JSF 구성 요소의 속성 id
및 binding
속성 에도 적용됩니다 .
뷰 빌드 시간은 XHTML / JSP 파일을 구문 분석하고 저장하는 JSF 컴포넌트 트리로 변환하는 것입니다 순간 UIViewRoot
의 FacesContext
. 뷰 렌더링 시간은 JSF 컴포넌트 트리가로 시작하여 HTML을 생성하려고하는 순간입니다 UIViewRoot#encodeAll()
. 따라서 코딩에서 예상 한대로 JSF UI 구성 요소와 JSTL 태그가 동기화되어 실행되지 않습니다. JSTL은 위에서 아래로 먼저 실행되어 JSF 컴포넌트 트리를 생성 한 다음 JSF가 위에서 아래로 다시 실행되어 HTML 출력을 생성합니다.
<c:forEach>
vs <ui:repeat>
예를 들어이 Facelets 마크 업은 <c:forEach>
다음을 사용하여 3 개 이상의 항목을 반복합니다 .
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
... 뷰 빌드 시간 동안 <h:outputText>
JSF 컴포넌트 트리에서 3 개의 개별 컴포넌트를 생성합니다.
<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>
구성 요소 ID의 고유성을 수동으로 확인해야하며보기 빌드 시간 동안 평가됩니다.
이 Facelets 마크 업은 <ui:repeat>
JSF UI 구성 요소 인을 사용하여 3 개 이상의 항목을 반복하는 동안 :
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
... 이미 JSF 컴포넌트 트리에서 그대로 종료되며, 현재의 반복 라운드를 기반으로 HTML 출력을 생성하기 위해 <h:outputText>
뷰 렌더 시간이 재사용 되는 동안 매우 동일한 컴포넌트가 있습니다
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
참고 그 <ui:repeat>
있는 Being 같은 NamingContainer
성분이 이미 반복 인덱스에 기초하여 상기 클라이언트 ID의 고유성을 보장; id
뷰 구성 시간 동안도 평가 #{item}
되고 뷰 렌더링 시간 동안 만 사용할 수 있으므로 자식 구성 요소의 속성으로 EL을 사용할 수 없습니다. 동일은 마찬가지입니다 h:dataTable
와 유사한 구성 요소.
<c:if>
/ <c:choose>
vsrendered
다른 예로,이 Facelets 마크 업은 조건부로 다른 태그를 추가하여 조건부로 추가합니다 <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>
... 구성 요소를 JSF 구성 요소 트리 type = TEXT
에만 추가하는 경우 <h:inputText>
:
<h:inputText ... />
이 Facelets 마크 업 동안 :
<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 이전의 Mojarra 버전에서 추가 속성이있는 서브 클래스를 처리 할 때 EL 문제가 발생할 수 있습니다 .
<c:set>
vs <ui:param>
그들은 서로 바꿔 쓸 수 없습니다. 이 뷰 <c:set>
는 EL 빌드 에서 변수를 설정합니다.이 변수는 뷰 빌드 시간 동안 태그 위치 이후 에만 볼 수 있지만 뷰 렌더링 시간 동안 뷰의 어느 곳에서나 액세스 할 수 있습니다 . 는 <ui:param>
Facelet 템플릿에 EL 변수로 포함 전달 <ui:include>
, <ui:decorate template>
또는 <ui:composition template>
. 이전 JSF 버전에는 <ui:param>
문제가있는 Facelet 템플릿 외부에서도 변수를 사용할 수 있는 버그가 있었으므로 절대 의존해서는 안됩니다.
<c:set>
없는 scope
속성은 별명처럼 동작합니다. 모든 범위에서 EL 표현식의 결과를 캐시하지 않습니다. 따라서 JSF 구성 요소를 반복하는 것과 같이 내부에서 완벽하게 사용할 수 있습니다. 따라서 아래 예를 들어 제대로 작동합니다.
<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}
전체 응용 프로그램에서 사용할 수 있습니다 .
같은 JSF 반복하는 구성 요소 내에서 사용되는 경우 JSTL을 사용하면 단지 예기치 않은 결과가 발생할 수 있습니다 <h:dataTable>
, <ui:repeat>
등, 또는 JSTL 태그 속성은 다음과 같은 JSF 이벤트의 결과에 의존 할 때 preRenderView
보기 빌드 시간 동안 사용할 수없는 모델의 양식 값 또는 제출 . 따라서 JSTL 구성 요소 트리 빌드의 흐름을 제어하기 위해 JSTL 태그 만 사용하십시오. JSF UI 구성 요소를 사용하여 HTML 출력 생성의 흐름을 제어하십시오. var
반복 JSF 구성 요소를 JSTL 태그 속성에 바인드하지 마십시오 . JSTL 태그 속성에서 JSF 이벤트에 의존하지 마십시오.
언제 당신은 당신이를 통해 백업 빈에 구성 요소 바인딩 할 필요가 있다고 생각 binding
, 또는를 통해 잡아 하나를 findComponent()
배킹와 콩에 자바 코드를 사용하여 어린이를 만들고 / 조작 new SomeComponent()
무엇을, 당신은 즉시 중지해야하지 대신 JSTL을 사용하는 것이 좋습니다. JSTL도 XML 기반이므로 JSF 구성 요소를 동적으로 만드는 데 필요한 코드는 훨씬 더 읽기 쉽고 유지 관리가 쉬워집니다.
2.1.18 이전의 Mojarra 버전은 JSTL 태그 속성에서 뷰 범위 Bean을 참조 할 때 부분 상태 저장에 버그가 있음을 알아야합니다. JSTL이 실행되는 시점에 전체 뷰 트리를 사용할 수 없기 때문에 전체 뷰 범위 Bean이 뷰 트리에서 검색되지 않고 새로 재생성됩니다. JSTL 태그 속성에 의해 뷰 범위 Bean에서 일부 상태를 예상하거나 저장하는 경우 예상 값을 리턴하지 않거나 실제 뷰 범위 Bean에서 "손실"되어 뷰 후에 복원됩니다. 나무가 지어졌습니다. 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 구성 요소 를 렌더링 하려는 경우 특히 또는 과 같은 JSF 반복 구성 요소의 현재 반복되는 항목을 나타내는 경우 rendered
JSF HTML 구성 요소 의 특성을 대신 사용하십시오 .#{lpc}
<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
. 프로젝트의 런타임 종속성이 손상되었습니다. Tomcat과 같은 JavaEE 이외의 서버를 사용 중이거나 JSTL 설치를 잊었거나 실수로 JSTL 1.0과 JSTL 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>
스위치 형 출력의 경우 PrimeFaces Extensions 의 스위치 면을 사용할 수 있습니다 .