Facelet을 요청할 때 BackingBean 방법이 여러 번 호출되는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/2272289

  •  20-09-2019
  •  | 
  •  

문제

나는 요즘 JSF + 페이스 넷에 대해 일하고 배우고 있습니다. BackingBean과 Facelet XHTML 페이지가 있습니다. Facelet-Page (한 번만)를 요청하면 백킹 빔 방법을 여러 번 호출합니다.

그 이유는 무엇입니까?

나는 특별한 것을 볼 수 없습니다. 미리 감사드립니다.

다음은 Facelet입니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<ui:composition template="index.xhtml">
    <ui:define name="content">
        <h:form>Name: <h:inputText id="nameFilterPattern" value="#{kundenBackingBean.nameFilterPattern}" /><h:commandButton value="Suchen"/></h:form>
        <h:dataTable var="kunde" value="#{kundenBackingBean.kunden}" rowClasses="rowHighlight, rowOrdinary">
            <h:column> 
                <f:facet name="header">
                    <h:outputText value="Kundennr" />
                </f:facet>
                <h:outputText value="#{kunde.kundenNr}"/>
            </h:column>
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Name" />
                </f:facet>
                <h:outputText value="#{kunde.name}"/>
            </h:column>
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Vorname" />
                </f:facet>
                <h:outputText value="#{kunde.vorname}"/>
            </h:column>
            <h:column>
                <h:outputLink>Details</h:outputLink>
            </h:column>
        </h:dataTable>
    </ui:define>
</ui:composition>
</body>
</html>

그리고 여기에 백킹 벡이 있습니다. GetKunden이 여러 번 호출됩니다.

@ManagedBean
@SessionScoped
public class KundenBackingBean extends AbstractBackingBean {

    private String nameFilterPattern;

    public List<Kunde> getKunden(){
        System.out.println("getKunden");
        return getApplication().getKunden(getNameFilterPattern());
    }

    public String getNameFilterPattern() {
        return nameFilterPattern;
    }

    public void setNameFilterPattern(String nameFilterPattern) {
        System.out.println("Name filter: " + nameFilterPattern);
        this.nameFilterPattern = nameFilterPattern;
    }

}
도움이 되었습니까?

해결책

콩의 getters는 바로 거기에 있습니다 입장 보기 측면에서 모델 데이터. 그들은 여러 번 부를 수 있습니다. 일반적으로 한두 번이지만, 특히 사용될 때 최대 수백 번 자랄 수 있습니다. UIData 구성 요소 또는 다른 속성에서 value (처럼 rendered, disabled, 등). 간단한 메소드 보조이기 때문에 일반적으로 해를 끼치 지 않으며 값 비싼 데이터로드 로직 또는 계산을 수행하는 것은 일반적으로 getters에서 수행되지 않기 때문입니다. 사전로드/초기화는 일반적으로 Bean 생성자 및/또는 Bean 동작 방법에서 수행됩니다. 실제로는 만해야합니다 반품 데이터 (필요한 경우에도 마찬가지입니다 게으른 하중).

만약에 getApplication().getKunden(getNameFilterPattern()); 꽤 비싼 작업을 수행하고 있습니다. 실제로 Bean 생성자 또는 Bean으로 이동해야합니다. @PostConstruct 방법, 또는 콩 초기화 블록 또는 콩 동작 방법 또는 소개 게으른 하중 게터의 패턴. 다음은이 모든 작업을 수행하는 방법을 보여주는 예입니다.

public class Bean {
    private String nameFilterPattern;
    private List<Kunde> kunden;

    // Load during bean construction.
    public Bean() {
        this.kunden = getApplication().getKunden(getNameFilterPattern());
    }

    // OR load during @PostConstruct (will be invoked AFTER construction and resource injection.
    @PostConstruct
    public void init() {
        this.kunden = getApplication().getKunden(getNameFilterPattern());
    }

    // OR during bean initialization (this is invoked BEFORE construction and will apply to ALL constructors).
    {
        this.kunden = getApplication().getKunden(getNameFilterPattern());
    }

    // OR during bean action method (invoked from h:commandLink/Button).
    public String submit() {
        this.kunden = getApplication().getKunden(getNameFilterPattern());
        return "navigationCaseOutcome";
    }

    // OR using lazy loading pattern in getter method.
    public List<Kunde> getKunden() {
        if (this.kunden == null) 
            this.kunden = getApplication().getKunden(getNameFilterPattern());
        }
        return this.kunden;
    }

당신의 특정한 경우, 나는 그것이 @PostConstruct (만약 nameFilterPattern a GET 요청 매개 변수) 또는 Bean 조치 방법 ( nameFilterPattern a POST 양식 입력 필드)가 적합합니다.

JSF 라이프 사이클에 대해 자세히 알아 보려면이 기능을 찾을 수 있습니다. 자기 연습 기사 유용한.

다른 팁

다른 곳에서 호출 할 수 있습니다 단계 JSF LifeCylce의. 내 베팅은 단계 일 것입니다 RestoreView 그리고 RenderResponse - 최근에 JSF를 사용하지 않았으므로 자세히 기억하지 못합니다.

최신 필터 패턴과 해당 클라이언트를 캐시 할 수 있습니다. 필터가 변경된 경우에만 클라이언트를 다시로드합니다. 이런 식 으로이 특정 문제를 해결하고 필터가 변경되지 않은 경우 데이터를 다시로드하지 마십시오.

private String nameFilterPattern;
private String lastNameFilterPatternLoaded;
private List<Kunde> clients;

public List<Kunde> getKunden(){
    System.out.println("getKunden");
    if( nameFilterPattern.equals( lastNameFilterPatternLoaded ) )
    {
        clients = getApplication().getKunden(getNameFilterPattern());
        lastNameFilterPatternLoaded = nameFilterPattern
    }
    return clients;
}

또는 사용할 수 있습니다 request 콩 (대신 session) 그리고 요청 당 한 번만 데이터를로드하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top