Wie wählt man den richtigen Bohnenbereich?


Antworten:


485

Einführung

Es repräsentiert den Umfang (die Lebensdauer) der Bohne. Dies ist leichter zu verstehen, wenn Sie mit der Funktionsweise einer grundlegenden Servlet-Webanwendung vertraut sind: Wie funktionieren Servlets? Instanziierung, Sitzungen, gemeinsam genutzte Variablen und Multithreading .


@Request/View/Flow/Session/ApplicationScoped

Eine @RequestScopedBean lebt so lange wie ein einzelner HTTP-Anforderungs-Antwort-Zyklus (beachten Sie, dass eine Ajax-Anforderung auch als einzelne HTTP-Anforderung zählt). Eine @ViewScopedBean lebt so lange, wie Sie mit derselben JSF-Ansicht durch Postbacks interagieren, die Aktionsmethoden aufrufen, die null/ voidohne Navigation / Umleitung zurückgeben. Eine @FlowScopedBean lebt so lange, wie Sie durch die angegebene Sammlung von Ansichten navigieren, die in der Flow-Konfigurationsdatei registriert sind. Eine @SessionScopedBean lebt so lange wie die eingerichtete HTTP-Sitzung. Eine @ApplicationScopedBean lebt so lange, wie die Webanwendung ausgeführt wird. Beachten Sie, dass der CDI @Modelim Grunde ein Stereotyp für ist @Named @RequestScoped, daher gelten dieselben Regeln.

Welcher Bereich ausgewählt werden soll, hängt ausschließlich von den Daten (dem Status) ab, die die Bean enthält und darstellt. Verwendung @RequestScopedfür einfache und nicht Ajax-Formulare / Präsentationen. Verwendung @ViewScopedfür umfangreiche Ajax-fähige dynamische Ansichten (Ajax-basierte Validierung, Rendering, Dialoge usw.). Verwendung @FlowScopedfür das Muster "Assistent" ("Fragebogen") zum Sammeln von Eingabedaten, die über mehrere Seiten verteilt sind. Verwendung @SessionScopedfür kundenspezifische Daten, z. B. den angemeldeten Benutzer und Benutzereinstellungen (Sprache usw.). Verwendung @ApplicationScopedfür anwendungsweite Daten / Konstanten, z. B. Dropdown-Listen, die für alle gleich sind, oder verwaltete Beans ohne Instanzvariablen und mit nur Methoden.

Wenn eine @ApplicationScopedBean für Daten mit Sitzungs- / Ansichts- / Anforderungsbereich missbraucht wird, wird sie für alle Benutzer freigegeben, sodass jeder andere die Daten des anderen sehen kann, was einfach falsch ist. Wenn eine @SessionScopedBean für Daten mit Ansichts- / Anforderungsbereich missbraucht wird, wird sie für alle Registerkarten / Fenster in einer einzelnen Browsersitzung freigegeben, sodass der Endbenutzer nach dem Wechsel zwischen Registerkarten möglicherweise Inkonsistenzen bei der Interaktion mit jeder Ansicht aufweist, was für die Benutzererfahrung schlecht ist. Wenn Sie eine @RequestScopedBean für Daten mit Ansichtsbereich missbrauchen, werden Daten mit Ansichtsbereich bei jedem einzelnen (Ajax-) Postback standardmäßig neu initialisiert, was möglicherweise zu nicht funktionierenden Formularen führt ( siehe auch Punkte 4 und 5 hier ). Missbrauch einer @ViewScopedBean für Daten im Anforderungs-, Sitzungs- oder Anwendungsbereich und Missbrauch von a@SessionScoped Bean für anwendungsbezogene Daten wirkt sich nicht auf den Client aus, belegt jedoch unnötigerweise den Serverspeicher und ist einfach ineffizient.

Beachten Sie, dass der Bereich eher nicht aufgrund von Auswirkungen auf die Leistung ausgewählt werden sollte, es sei denn, Sie haben wirklich einen geringen Speicherbedarf und möchten vollständig zustandslos werden. Sie müssen ausschließlich @RequestScopedBeans verwenden und mit Anforderungsparametern herumspielen, um den Status des Clients beizubehalten. Beachten Sie außerdem, dass es bei einer einzelnen JSF-Seite mit Daten mit unterschiedlichem Gültigkeitsbereich durchaus sinnvoll ist, diese in separaten Backing Beans in einem Bereich abzulegen, der dem Datenbereich entspricht. Die Beans können @ManagedPropertybei JSF-verwalteten Beans oder @Injectbei CDI-verwalteten Beans nur über einander zugreifen .

Siehe auch:


@CustomScoped/NoneScoped/Dependent

Es wird in Ihrer Frage nicht erwähnt, aber (Legacy) JSF unterstützt auch @CustomScopedund @NoneScoped, die in der realen Welt selten verwendet werden. Sie @CustomScopedmüssen auf eine benutzerdefinierte Map<K, Bean>Implementierung in einem breiteren Bereich verweisen, die überschrieben wurde Map#put()und / oder Map#get()um eine genauere Kontrolle über die Erstellung und / oder Zerstörung von Beans zu erhalten.

Der JSF @NoneScopedund der CDI leben @Dependentgrundsätzlich so lange wie eine einzelne EL-Bewertung auf der Bohne. Stellen Sie sich ein Anmeldeformular mit zwei Eingabefeldern vor, die auf eine Bean-Eigenschaft verweisen, und einer Befehlsschaltfläche, die auf eine Bean-Aktion verweist. Mit insgesamt drei EL-Ausdrücken werden dann effektiv drei Instanzen erstellt. Eine mit dem festgelegten Benutzernamen, eine mit dem festgelegten Kennwort und eine, für die die Aktion aufgerufen wird. Normalerweise möchten Sie diesen Bereich nur für Bohnen verwenden, die so lange leben sollen wie die Bohne, in die sie injiziert wird. Wenn also ein @NoneScopedoder @Dependentin ein injiziert @SessionScopedwird, lebt es so lange wie die @SessionScopedBohne.

Siehe auch:


Flash-Bereich

Als letztes unterstützt JSF auch den Flash-Bereich. Es wird von einem kurzen lebenden Cookie unterstützt, das einer Dateneingabe im Sitzungsbereich zugeordnet ist. Vor der Umleitung wird für die HTTP-Antwort ein Cookie mit einem Wert gesetzt, der der Dateneingabe im Sitzungsbereich eindeutig zugeordnet ist. Nach der Umleitung wird das Vorhandensein des Flash-Scope-Cookies überprüft und die mit dem Cookie verknüpfte Dateneingabe aus dem Sitzungsbereich entfernt und in den Anforderungsbereich der umgeleiteten Anforderung gestellt. Schließlich wird das Cookie aus der HTTP-Antwort entfernt. Auf diese Weise hat die umgeleitete Anforderung Zugriff auf Daten mit Anforderungsbereich, die in der ursprünglichen Anforderung vorbereitet wurden.

Dies ist eigentlich nicht als verwalteter Bean-Bereich verfügbar, dh es gibt keine @FlashScoped. Der Flash-Bereich ist nur als Karte über ExternalContext#getFlash()in verwalteten Beans und #{flash}in EL verfügbar .

Siehe auch:


4
Ich denke, ein Verweis auf Ihre Antwort auf die Frage " Wie und wann wird eine View Scope Bean in JSF zerstört? " Ist hier relevant.
Lii

3
@Cold: Dies ist ein alter CDI-Bereich, der in JSF 2.2 durch ersetzt wird @FlowScoped(kein manuelles Starten / Stoppen erforderlich).
BalusC

1
Und DeltaSpike hat zusätzlich ViewAccesscopedundWindowScoped
Kukeltje

@BalusC, ich denke, es gibt ein Problem mit ViewScopedBean in MyFaces 2.2. Ich habe derzeit ein Problem mit ViewScopedBean und Ajax, das ich hier gepostet habe . In MyFaces JIRA gibt es auch eine Diskussion zu diesem Thema.
Tapas Bose

CDI definiert vier integrierte Bereiche: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped Warum unterscheiden sich die von Ihnen beschriebenen Bereiche?
Hosein Aqajani

122

Seit JSF 2.3 sind alle im Paketpaket definierten Bean-Bereiche javax.faces.beanveraltet, um die Bereiche an CDI auszurichten. Darüber hinaus sind sie nur anwendbar, wenn Ihre Bean @ManagedBeanAnmerkungen verwendet. Wenn Sie JSF-Versionen unter 2.3 verwenden, lesen Sie die Legacy-Antwort am Ende.


Ab JSF 2.3 gibt es folgende Bereiche, die für JSF-Backing-Beans verwendet werden können:

1 .@javax.enterprise.context.ApplicationScoped : Der Anwendungsbereich bleibt für die gesamte Dauer der Webanwendung bestehen. Dieser Bereich wird von allen Anforderungen und allen Sitzungen gemeinsam genutzt. Dies ist nützlich, wenn Sie Daten für die gesamte Anwendung haben.

2 .@javax.enterprise.context.SessionScoped : Der Sitzungsbereich bleibt von der Einrichtung einer Sitzung bis zur Beendigung der Sitzung bestehen. Der Sitzungskontext wird von allen Anforderungen gemeinsam genutzt, die in derselben HTTP-Sitzung auftreten. Dies ist nützlich, wenn Sie keine Daten für einen bestimmten Client für eine bestimmte Sitzung speichern möchten.

3 .@javax.enterprise.context.ConversationScoped : Der Konversationsbereich bleibt als Protokoll erhalten, solange die Bean lebt. Der Bereich bietet zwei Methoden: Conversation.begin()und Conversation.end(). Diese Methoden sollten explizit aufgerufen werden, um das Leben einer Bohne zu beginnen oder zu beenden.

4 .@javax.enterprise.context.RequestScoped : Der Anforderungsumfang ist von kurzer Dauer. Es beginnt, wenn eine HTTP-Anforderung gesendet wird, und endet, nachdem die Antwort an den Client zurückgesendet wurde. Wenn Sie eine verwaltete Bean in den Anforderungsbereich einfügen, wird mit jeder Anforderung eine neue Instanz erstellt. Wenn Sie sich Gedanken über die Kosten für die Speicherung des Sitzungsbereichs machen, sollten Sie den Anforderungsumfang berücksichtigen.

5 .@javax.faces.flow.FlowScoped : Der Flow-Bereich bleibt so lange bestehen, wie der Flow lebt. Ein Flow kann als enthaltener Satz von Seiten (oder Ansichten) definiert werden, die eine Arbeitseinheit definieren. Der Flow-Bereich war aktiv, solange der Benutzer mit im Flow navigiert.

6 .@javax.faces.view.ViewScoped : Eine Bean im Ansichtsbereich bleibt bestehen, während dieselbe JSF-Seite erneut angezeigt wird. Sobald der Benutzer zu einer anderen Seite navigiert, verlässt der Bean den Gültigkeitsbereich.


Die folgende Legacy-Antwort gilt für die JSF-Version vor 2.3

Ab JSF 2.x gibt es 4 Bean Scopes:

  • @ SessionScoped
  • @RequestScoped
  • @ApplicationScoped
  • @ ViewScoped

Sitzungsbereich: Der Sitzungsbereich bleibt vom Zeitpunkt der Einrichtung einer Sitzung bis zur Beendigung der Sitzung bestehen. Eine Sitzung wird beendet, wenn die Webanwendung die ungültige Methode für das HttpSession-Objekt aufruft oder wenn das Zeitlimit überschritten wird.

RequestScope: Der Anforderungsbereich ist von kurzer Dauer. Es beginnt, wenn eine HTTP-Anforderung gesendet wird, und endet, nachdem die Antwort an den Client zurückgesendet wurde. Wenn Sie eine verwaltete Bean in den Anforderungsbereich einfügen, wird mit jeder Anforderung eine neue Instanz erstellt. Wenn Sie sich Gedanken über die Kosten für die Speicherung des Sitzungsbereichs machen, sollten Sie den Anforderungsumfang berücksichtigen.

ApplicationScope: Der Anwendungsbereich bleibt für die gesamte Dauer der Webanwendung bestehen. Dieser Bereich wird von allen Anforderungen und allen Sitzungen gemeinsam genutzt. Sie fügen verwaltete Beans in den Anwendungsbereich ein, wenn eine einzelne Bean für alle Instanzen einer Webanwendung freigegeben werden soll. Die Bean wird erstellt, wenn sie zum ersten Mal von einem Benutzer der Anwendung angefordert wird, und bleibt so lange aktiv, bis die Webanwendung vom Anwendungsserver entfernt wird.

ViewScope: Der Ansichtsbereich wurde in JSF 2.0 hinzugefügt. Ein Bean im Ansichtsbereich bleibt bestehen, während dieselbe JSF-Seite erneut angezeigt wird. (In der JSF-Spezifikation wird der Begriff "Ansicht" für eine JSF-Seite verwendet.) Sobald der Benutzer zu einer anderen Seite navigiert, verlässt die Bean den Gültigkeitsbereich.

Wählen Sie den Umfang, den Sie basierend auf Ihrer Anforderung haben.

Quelle: Core Java Server Faces 3. Auflage von David Geary & Cay Horstmann [Seite Nr. 51 - 54] Geben Sie hier die Bildbeschreibung ein


Könnten Sie bitte klarstellen, was Sie unter "der ungültigen Methode für das HttpSession-Objekt" verstehen: invalidate()Methode oder ungültige Methode?
Alexander Pozdneev

1
Ein bisschen alt und vielleicht zu spät zur Antwort, aber um es zu verdeutlichen: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();In Ihrer "Logout Bean" aufgerufen zu werden, ist das, was er meint.
Roland

1
Es wurde eine Legacy-Antwort, im Moment gibt es 8 Bereiche
Ewoks

@KishorPrakash: eine Weile ist jetzt 6 Monate her. ;-)
Kukeltje

@ Kukeltje: Entschuldigung, ich bin dabei.
Kishor Prakash
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.