Pergunta

Estou trabalhando e aprendendo sobre o JSF + Facelets atualmente. Eu tenho uma página de backingbean e uma página XHTML do Facelet. Quando solicito a página do Facelet (apenas uma vez), o método de backing-bean é chamado várias vezes.

Qual poderia ser a razão para isso?

Não consigo ver nada de especial. Desde já, obrigado.

Aqui está o 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>

E aqui está o feijão de apoio. O método Getkunden é chamado várias vezes:

@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;
    }

}
Foi útil?

Solução

Os getters de um feijão estão lá apenas para Acesso Dados do modelo do lado da exibição. Eles podem ser chamados várias vezes. Geralmente uma ou duas vezes, mas isso pode crescer até centenas de vezes, especialmente quando também usado em UIData componentes ou em outros atributos que não value (Curti rendered, disabled, etc). Normalmente, isso não prejudica, pois é apenas uma simples inspeção de métodos e fazer lógica ou cálculos caros de carregamento de dados geralmente não deve ser feito nos getters. A pré -carga/inicialização geralmente deve ser feita no construtor de feijão e/ou nos métodos de ação do feijão. Getters deve de fato apenas Retorna os dados (se necessário também fazem carregamento lento).

Se getApplication().getKunden(getNameFilterPattern()); está fazendo uma tarefa muito cara, você deve realmente movê -lo para o construtor de feijão ou feijão @PostConstruct método, ou bloqueio de inicialização do feijão, ou método de ação do feijão, ou introdução carregamento lento padrão no getter. Aqui está um exemplo que mostra como fazer isso tudo:

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;
    }

No seu caso específico, acho que é o @PostConstruct (se o nameFilterPattern deve ser obtido de um GET parâmetro de solicitação), ou apenas o método de ação do feijão (se nameFilterPattern deve ser obtido de um POST campo de entrada de formulário) é adequado.

Para saber mais sobre o ciclo de vida do JSF, você pode encontrar isso Artigo de auto-prática útil.

Outras dicas

Pode ser chamado de diferente fases do JSF Lifecylce. Minha aposta seria as fases RestoreView e depois RenderResponse - Não tenho usado o JSF ultimamente, então não me lembro disso em detalhes.

Você pode cache o padrão de filtro mais recente e os clientes correspondentes. Você recarregue os clientes apenas se o filtro foi alterado. Dessa forma, você resolve esse problema específico, além de evitar recarregar os dados se o filtro não alterar.

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;
}

Ou você pode usar um request Bean (em vez de session) e certifique -se de carregar os dados apenas uma vez por solicitação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top