JSF에서 '바인딩'속성은 어떻게 작동합니까? 언제 어떻게 사용해야합니까?
JSF 에는 value
속성과 binding
속성을 구분하는 많은 자료가 있습니다 .
두 가지 접근 방식이 서로 어떻게 다른지에 관심이 있습니다. 주어진:
public class User {
private String name;
private UICommand link;
// Getters and setters omitted.
}
<h:form>
<h:commandLink binding="#{user.link}" value="#{user.name}" />
</h:form>
value
속성이 지정 될 때 일어나는 일은 매우 간단 합니다. getter가 실행되어 Bean 의 name
속성 값 을 반환합니다 User
. 값은 HTML 출력으로 인쇄됩니다.
하지만 어떻게 binding
작동 하는지 이해할 수 없었습니다 . 생성 된 HTML은 어떻게 bean 의 link
속성 과 바인딩을 유지 User
합니까?
다음은 수동 미화 및 주석 처리 후 생성 된 출력의 관련 부분입니다 (ID j_id_jsp_1847466274_1
가 자동 생성되었으며 두 개의 숨겨진 입력 위젯이 있음을 참고하십시오). Sun의 JSF RI 버전 1.2를 사용하고 있습니다.
<form action="/TestJSF/main.jsf" enctype="application/x-www-form-urlencoded"
id="j_id_jsp_1847466274_1" method="post" name="j_id_jsp_1847466274_1">
<input name="j_id_jsp_1847466274_1" type="hidden" value="j_id_jsp_1847466274_1">
<a href="#" onclick="...">Name</a>
<input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState"
type="hidden" value="-908991273579182886:-7278326187282654551">
</form>
여기에 어디에 binding
저장되어 있습니까?
어떻게 작동합니까?
JSF보기 (Facelets / JSP 파일)가 빌드 / 복원되면 JSF 컴포넌트 트리가 생성됩니다. 그 순간 뷰 빌드 시간 , 모든 binding
속성이 평가됩니다 ( JSTL과 같은 속성 및 태그 핸들러와 함께id
). 구성 요소 트리에 추가하기 전에 JSF 구성 요소를 만들어야하는 경우 JSF는 binding
속성이 미리 생성 된 구성 요소 (예 : non- null
)를 반환 하는지 확인한 다음 사용합니다. 미리 생성되지 않은 경우 JSF는 구성 요소를 "일반적인 방법"으로 binding
자동 생성하고 자동 생성 된 구성 요소 인스턴스를 인수로 사용하여 속성 뒤에 setter를 호출합니다 .
효과에서는 구성 요소 트리의 구성 요소 인스턴스 참조를 범위 변수에 바인딩합니다. 이 정보는 구성 요소 자체의 생성 된 HTML 표현에 표시되지 않습니다. 이 정보는 어쨌든 생성 된 HTML 출력과 관련이 없습니다. 양식이 제출되고보기가 복원되면 JSF 구성 요소 트리가 처음부터 다시 작성되고 모든 binding
속성이 위 단락에서 설명한대로 다시 평가됩니다. 컴포넌트 트리가 재생성 된 후 JSF는 JSF보기 상태를 컴포넌트 트리로 복원합니다.
구성 요소 인스턴스는 요청 범위입니다!
알고 이해해야 할 중요한 것은 구체적인 구성 요소 인스턴스가 효과적으로 요청 범위가 지정된다는 것입니다. 모든 요청에 대해 새로 생성되며 해당 속성은 복원보기 단계 동안 JSF보기 상태의 값으로 채워집니다. 따라서 구성 요소를 지원 빈의 속성에 바인딩하는 경우 지원 빈은 절대적으로 요청 범위보다 더 넓은 범위에 있지 않아야 합니다. JSF 2.0 사양 3.1.5 장을 참조하십시오 .
3.1.5 구성 요소 바인딩
...
컴포넌트 바인딩은 종종 Managed Bean 생성 기능을 통해 동적으로 인스턴스화되는 JavaBeans와 함께 사용됩니다 (섹션 5.8.1“VariableResolver 및 기본 VariableResolver”참조). 응용 프로그램 개발자는 "요청"범위에서 구성 요소 바인딩식이 가리키는 관리 빈을 배치하는 것이 좋습니다. 이는 UIComponent 인스턴스가 단일 스레드 내부에서 실행되는 것에 의존하기 때문에 세션 또는 응용 프로그램 범위에 배치하려면 스레드 안전성이 필요하기 때문입니다. 또한 구성 요소 바인딩을 "세션"범위에 배치 할 때 메모리 관리에 잠재적으로 부정적인 영향을 미칠 수 있습니다.
그렇지 않으면 구성 요소 인스턴스가 여러 요청간에 공유 되어 뷰에 선언 된 유효성 검사기, 변환기 및 리스너가 이전 요청의 기존 구성 요소 인스턴스에 다시 연결되므로 " 중복 구성 요소 ID "오류 및 "이상한"동작이 발생할 수 있습니다. 증상은 명확합니다. 구성 요소가 바인드 된 것과 동일한 범위 내에서 각 요청에 대해 한 번 더 여러 번 실행됩니다.
그리고 과부하 상태에서 (즉, 여러 다른 HTTP 요청 (스레드)이 동시에 매우 동일한 구성 요소 인스턴스에 액세스하고 조작하는 경우) 조만간 UIComponent.popComponentFromEL 또는 Java 스레드 에서 스레드가 멈춤 과 함께 애플리케이션 충돌에 직면 할 수 있습니다. Richfaces UIDataAdaptorBase 및 내부 HashMap 을 사용하거나 JSF가 뷰 상태 (예 : 스택 추적 표시 또는 메서드 등)를 저장하거나 복원하는 동안 JSF 구현 소스 코드에서 "이상한" IndexOutOfBoundsException
또는 ConcurrentModificationException
직접 오는 100 % CPU 사용률 .saveState()
restoreState()
binding
빈 속성에 사용 하는 것은 나쁜 습관입니다.
어쨌든 binding
이 방법을 사용 하면 요청 범위 빈에서도 전체 구성 요소 인스턴스를 빈 속성에 바인딩하는 것은 JSF 2.xa에서 매우 드문 사용 사례이며 일반적으로 모범 사례가 아닙니다. 디자인 냄새를 나타냅니다. 당신은 일반적으로보기 측에서 구성 요소를 선언하고 바인드 자신의 런타임과 같은 속성 value
, 그리고 아마도 다른 사람들이 좋아하는 styleClass
, disabled
, rendered
일반 콩 속성 등. 그런 다음 전체 구성 요소를 잡고 속성과 관련된 setter 메서드를 호출하는 대신 원하는 빈 속성을 정확하게 조작합니다.
구성 요소의 요구가 "동적으로 작성"할 때의 경우 정적 모델을 기반으로 더 나은 사용하는 것입니다 JSTL처럼보기 빌드시 태그를 필요한 경우에, 태그 파일 대신에, createComponent()
, new SomeComponent()
, getChildren().add()
어떤이 없습니다. 이전 JSP의 스 니펫을 JSF와 동등한 것으로 리팩터링하는 방법 도 참조하십시오 .
구성 요소의 요구가 "동적으로 렌더링"하는 경우 또는 동적 모델을 기반으로, 다음 그냥 사용 반복자 구성 요소를 ( <ui:repeat>
, <h:dataTable>
, 등). JSF 구성 요소를 동적으로 추가하는 방법 도 참조하십시오 .
Composite components is a completely different story. It's completely legit to bind components inside a <cc:implementation>
to the backing component (i.e. the component identified by <cc:interface componentType>
. See also a.o. Split java.util.Date over two h:inputText fields representing hour and minute with f:convertDateTime and How to implement a dynamic list with a JSF 2.0 Composite Component?
Only use binding
in local scope
However, sometimes you'd like to know about the state of a different component from inside a particular component, more than often in use cases related to action/value dependent validation. For that, the binding
attribute can be used, but not in combination with a bean property. You can just specify an in the local EL scope unique variable name in the binding
attribute like so binding="#{foo}"
and the component is during render response elsewhere in the same view directly as UIComponent
reference available by #{foo}
. Here are several related questions where such a solution is been used in the answer:
- Validate input as required only if certain command button is pressed
- How to render a component only if another component is not rendered?
- JSF 2 dataTable row index without dataModel
- Primefaces dependent selectOneMenu and required="true"
- Validate a group of fields as required when at least one of them is filled
- How to change css class for the inputfield and label when validation fails?
- Getting JSF-defined component with Javascript
Use an EL expression to pass a component ID to a composite component in JSF
(and that's only from the last month...)
See also:
- How to use component binding in JSF right ? (request-scoped component in session scoped bean)
- View scope: java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
- Binding attribute causes duplicate component ID found in the view
each JSF component renders itself out to HTML and has complete control over what HTML it produces. There are many tricks that can be used by JSF, and exactly which of those tricks will be used depends on the JSF implementation you are using.
- Ensure that every from input has a totaly unique name, so that when the form gets submitted back to to component tree that rendered it, it is easy to tell where each component can read its value form.
- The JSF component can generate javascript that submitts back to the serer, the generated javascript knows where each component is bound too, because it was generated by the component.
For things like hlink you can include binding information in the url as query params or as part of the url itself or as matrx parameters. for examples.
http:..../somelink?componentId=123
would allow jsf to look in the component tree to see that link 123 was clicked. or it could ehtp:..../jsf;LinkId=123
The easiest way to answer this question is to create a JSF page with only one link, then examine the html output it produces. That way you will know exactly how this happens using the version of JSF that you are using.
'programing tip' 카테고리의 다른 글
jQuery는 DOM 노드를 얻습니까? (0) | 2020.10.27 |
---|---|
Windows에서 CR LF를 사용하는 이유는 무엇입니까? (0) | 2020.10.27 |
PHP 세션의 최대 크기 (0) | 2020.10.27 |
std :: lexical_cast-그런 것이 있습니까? (0) | 2020.10.27 |
Google 문서 / 드라이브-제목에 번호 매기기 (0) | 2020.10.27 |