Ich gehe das Java EE 6-Tutorial durch und versuche, den Unterschied zwischen zustandslosen und zustandsbehafteten Session-Beans zu verstehen. Wenn zustandslose Session-Beans ihren Status zwischen Methodenaufrufen nicht beibehalten, warum verhält sich mein Programm dann so, wie es ist?
package mybeans;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
Der Kunde
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Ich hatte erwartet, dass getNumber jedes Mal 0 zurückgibt, aber es gibt 1 zurück, und das Neuladen des Servlets in meinem Browser erhöht es weiter. Das Problem liegt in meinem Verständnis der Funktionsweise zustandsloser Session Beans und natürlich nicht in den Bibliotheken oder dem Anwendungsserver. Kann mir jemand ein einfaches Beispiel für eine zustandslose Session-Bean geben, die sich anders verhält, wenn Sie sie in stateful ändern?
java
jakarta-ee
ejb
ejb-3.1
stateful-session-bean
Stanley Kelly
quelle
quelle
Antworten:
Der wichtige Unterschied besteht nicht in privaten Mitgliedsvariablen, sondern darin, den Status einem bestimmten Benutzer zuzuordnen (denken Sie an "Warenkorb").
Das Stateful-Stück Stateful Session Bean entspricht der Sitzung in Servlets. Mit Stateful Session Beans kann Ihre App diese Sitzung auch dann noch haben, wenn kein Webclient vorhanden ist. Wenn der App-Server eine zustandslose Session-Bean aus dem Objektpool abruft, weiß er, dass sie zur Erfüllung JEDER Anforderung verwendet werden kann, da sie keinem bestimmten Benutzer zugeordnet ist.
Eine Stateful-Session-Bean muss an den Benutzer verteilt werden, der sie ursprünglich erhalten hat, da ihre Warenkorbinformationen nur ihnen bekannt sein sollten. Der App-Server stellt dies sicher. Stellen Sie sich vor, wie beliebt Ihre App wäre, wenn Sie mit dem Einkaufen beginnen könnten, und dann gab mir der App-Server Ihre Stateful Session Bean, als ich mitkam!
Ihr privates Datenmitglied ist also zwar "Bundesstaat", aber kein "Einkaufswagen". Versuchen Sie, Ihr (sehr gutes) Beispiel so zu wiederholen, dass die inkrementierte Variable einem bestimmten Benutzer zugeordnet ist. Inkrementieren Sie es, erstellen Sie einen neuen Benutzer und prüfen Sie, ob er den inkrementierten Wert noch sehen kann. Bei korrekter Ausführung sollte jeder Benutzer nur seine Version des Zählers sehen.
quelle
Stateless Session Beans (SLSB) sind nicht an einen Client gebunden , und es gibt keine Garantie dafür, dass ein Client bei jedem Methodenaufruf dieselbe Instanz erhält (einige Container können bei jeder Methodenaufrufsitzung Beans erstellen und zerstören. Dies ist eine implementierungsspezifische Entscheidung , aber Instanzen werden normalerweise gepoolt - und ich erwähne keine Clusterumgebungen). Mit anderen Worten, obwohl zustandslose Beans möglicherweise Instanzvariablen enthalten, sind diese Felder nicht für einen Client spezifisch. Verlassen Sie sich daher zwischen Remoteaufrufen nicht auf sie.
Im Gegensatz dazu Stateful Session Beans (SFSB) ist gewidmet , um einen Client für ihr ganzes Leben, gibt es keinen Austausch oder die Bündelung von Instanzen (aus dem Gedächtnis nach der Passivierung vertrieben werden kann , Ressourcen zu sparen , aber das ist ein andere Geschichte) und Konversations Zustand zu halten . Dies bedeutet, dass die Instanzvariablen der Bean zwischen Methodenaufrufen Daten relativ zum Client halten können. Dies ermöglicht voneinander abhängige Methodenaufrufe (Änderungen, die von einer Methode vorgenommen werden, wirken sich auf nachfolgende Methodenaufrufe aus). Mehrstufige Prozesse (ein Registrierungsprozess, ein Warenkorb, ein Buchungsprozess ...) sind typische Anwendungsfälle für SFSB.
Eine Sache noch. Wenn Sie SFSB verwenden, müssen Sie vermeiden, sie in Klassen mit mehreren Threads einzufügen, z. B. Servlets und JSF-verwaltete Beans (Sie möchten nicht, dass sie von allen Clients gemeinsam genutzt werden). Wenn Sie SFSB in Ihrer Webanwendung verwenden möchten, müssen Sie eine JNDI-Suche durchführen und die zurückgegebene EJB-Instanz
HttpSession
für zukünftige Aktivitäten im Objekt speichern . Sowas in der Art:quelle
Staatenlos und zustandsbehaftet bedeuten in diesem Zusammenhang nicht ganz das, was Sie erwarten könnten.
Statefulness mit EJBs bezieht sich auf das, was ich Konversationsstatus nenne . Das klassische Beispiel ist eine Flugbuchung. Wenn es aus drei Schritten besteht:
Stellen Sie sich vor, jeder dieser Methoden ist ein Methodenaufruf für eine Session-Bean. Eine Stateful Session Bean kann diese Art von Konversation aufrechterhalten, sodass sie sich merkt, was zwischen Anrufen passiert.
Zustandslose Session-Beans verfügen nicht über eine solche Kapazität für den Konversationsstatus.
Globale Variablen innerhalb einer Session Bean (zustandslos oder statusbehaftet) sind etwas ganz anderes. Bei Stateful Session Beans wird ein Pool von Beans erstellt (da eine Bean jeweils nur in einer Konversation verwendet werden kann), während zustandslose Sesion Beans häufig nur eine Instanz haben, wodurch die globale Variable funktioniert, aber ich denke nicht Dies ist unbedingt garantiert.
quelle
Die großen Unterschiede zwischen den beiden Haupttypen von Session Beans sind:
Staatenlose Bohnen
Stateful Beans
quelle
Dies geschieht, weil der Container nur eine Bean-Instanz im Pool hat, die für alle Aufrufe wiederverwendet wird. Wenn Sie die Clients parallel ausführen, wird ein anderes Ergebnis angezeigt, da der Container mehr Bean-Instanzen im Pool erstellt.
quelle
Es hat gute Antworten. Ich möchte eine kleine Antwort hinzufügen. Stateless Bean sollte nicht zum Speichern von Clientdaten verwendet werden. Es sollte verwendet werden, um "Aktionen oder Prozesse zu modellieren, die auf einen Schlag ausgeführt werden können".
quelle
Gute Frage,
Versuchen Sie diesen Code (ändern Sie MyBean Stateful / Stateless.):
Servlet_1
Servlet_2
Fall: MyBean - @ Stateless
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo_war_exploded / newServletClient
3
http: // localhost: 8080 / MYServletDemo / ServletClient
4
Fall: MyBean - @ Stateful
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo / newServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
3
quelle