답변:
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 반복 구성 요소의 현재 반복되는 항목을 나타내는 경우 renderedJSF 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>UIComponentUIComponent
<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 의 스위치 면을 사용할 수 있습니다 .