1: Einführung in die Frühlingssitzung
1. Einführung
Die Sitzung war schon immer ein schwieriges Problem, das wir bei Clustern lösen müssen. In der Vergangenheit konnten wir es von Servlet-Behältern wie Tomcat-Redis-Session-Manager und Memcached-Session-Manager lösen, die vom Open-Source-Servlet-Container-Tomcat bereitgestellt werden.
Oder IP_HASH durch Load Balancing wie Nginx und Ruting an einen bestimmten Server durchführen.
Beide Methoden haben jedoch Nachteile.
Frühlingssitze ist ein Projekt unter dem Frühjahr. Es ersetzt die vom Servlet Container implementierte HTTPSession durch Frühlingssitzung und konzentriert sich auf die Lösung von Sitzungsmanagementproblemen. Es kann schnell und nahtlos in unsere Anwendungen integriert werden.
2. Unterstützungsfunktionen
1) Speichern Sie einfach Sitzungen in Speicherbehältern von Drittanbietern. Das Framework bietet Redis, JVM -Karte, Mongo, Gemfire, Hazelcast, JDBC und andere Behälter für die Aufbewahrung von Sitzungen.
2) Der gleiche Browser und dieselbe Website unterstützen mehrere Sitzungsprobleme.
3) RESTFUFFURAPI ist nicht auf Kekse angewiesen. Der Jessionid kann durch den Kopfball geleitet werden
4) Kombinieren von WebSocket und Frühlingssitzung, um das Lebenszyklusmanagement zu synchronisieren.
3. Integrationsmethode
Die Integrationsmethode ist sehr einfach. Schauen Sie sich einfach die Beispiele und den Leitfaden auf der offiziellen Website an. http://docs.spring.io/spring-Session/docs/1.3.0.release/reference/html5/
Es ist hauptsächlich in die folgenden Integrationsschritte unterteilt:
1) Abhängigkeitspaket einführen
2) Annotationsmethode oder XML -Methode zum Konfigurieren von Speichermethoden für bestimmte Speicherbehälter, wie z.
<Kontext: Annotation-Konfiguration/** Initialisieren Sie alle Frühlingssitzungen und setzen Sie SpringsessionFilter in ioc **/<beanclass = "org.springFramework.Session.data.Redis.Config.annotation <beanclass = "org.springframework.data.redis.connection.lettuce.lettuceConnectionFactory"/>
3) Konfigurieren Sie Web.xml in der XML -Methode, konfigurieren Sie SpringSessionFilter in die Filterkette
<Filter> <Filter-name> SpringSessionRepositoryFilter </filter-name> <filterklasse> org.springframework.web.filter.delegatingfilterProxy </Filter-Class> </filter> <Filter-Mapping> <Filter-name> SpringSessionRepositoryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFiloryFilory-Filter-Name> </filter-mapping <URL-Muster>/*</url-puster> <Iffizcher> Anforderung </Dispatcher> <Iffizcher> Fehler </Dispatcher> </filter-mapping>
Zwei: Interne Analyse des Frühlingssitzungsrahmens
1. Rahmen hochrahmen abstrakter Strukturdiagramm
2. Spring-Session-Session-SCHWEISS DER SERVLET-Anfrage und Redisspeicherbezogene Probleme
Das allgemeine Prinzip der Frühlingssitzung ersetzt die Anfrage des Anwendungsservers nahtlos:
1. Passen Sie einen Filter an und implementieren Sie die Dofilter -Methode
2. Erben Sie die Klassen HttpServletRequestWrapper und httpServletResponsewrapper und überschreiben Sie die GetSession und andere zugehörige Methoden (die relevante Sitzungspray -Containerbetriebsklasse wird in diesen Methoden aufgerufen).
3. In dem Dofilter -Schritt im ersten Schritt sind neue Anforderungs- und Antwortklassen im zweiten Schritt. und übergeben Sie sie getrennt an die Filterkette
4. Konfigurieren Sie den Filter mit der ersten Position der Filterkette
/** Diese Klasse ist der Quellcode von 1.30 der Frühlingssitzung, und es ist auch die Schlüsselklasse, die die ersten bis dritten Schritte über die oberhalb von **/öffentlichen Klassen-SessionRepositoryFilter <S erweitert. private servletContext ServletContext; /** SessionID -Zustellungsschnittstelle. Derzeit wird die Spring-Session mit zwei Implementierungsklassen ausgestattet 1. Cookie-Methode: CookiehttpSessionStrategy 2.http Header-Methode: HeaderHttpSessionStrategy Natürlich können wir auch andere Methoden anpassen. **/ private MultihttpSessionStrategy httpSsionStrategy = new CookiehttpSessionStrategy (); public SessionRepositoryFilter (SessionRepository <S> SessionRepository) {if (sessionRepository == null) {werfen neuer IllegalArgumentException ("SessionRepository kann nicht null sein"); } this.SessionRepository = SessionRepository; } public void sethttpSessionStrategy (httpSsionStrategy httpSessionStrategy) {if (httpSsionSsionStrategy == null) {Neue IllegalArgumentException ("httpSsionSsionStrategy kann nicht null sein"); } /** In der vorherigen Einführung der Frühlingssitzungsfunktion wissen wir, dass die Frühlingssitzung mehrere Sitzungen in einem einzelnen Browser unterstützen kann, der durch das MultihttpSessionStrategyadapter erreicht wird. Jeder Browser verfügt über eine Sitzung, diese Sitzung hat jedoch mehrere Aliase (gemäß der Registerkarte des Browsers). Zum Beispiel: alias 1 sessionID alias 2 sessionID ... und dieser Alias wird durch die URL weitergeleitet, was das Prinzip mehrerer Sitzungen durch einen einzelnen Browser ist } public void sethttpSessionStrategy (multihttpSsionStrategy httpSsionSsionStrategy) {if (httpSsionSsionStrategy == null) {neue illegalArgumentException ("httpSsionSsionSsionStrategy kann nicht null sein"); } this.httpSessionStrategy = httpSessionStrategy; } /** Diese Methode entspricht dem Umschreiben von Dofilter, aber die Frühlingssitzung hat eine weitere Kapselungsschicht. Erstellen Sie in dieser Methode eine benutzerdefinierte Anforderung und Antwort und geben Sie sie dann an die Filterkettenfilterchain **/ @Override geschütztes void dofilterinternal (httpServletRequest Request, HttpServletResponse -Antwort, Filterchain -Filterchain) veranlasst ServletException, IOException. /** ServletRequest durch Frühlingssitzung umgeschrieben. Diese Klasse erbt httpServletRequestWrapper **/ SessionRepositoryRequestWrapper WrapedRequest = new SessionRepositoryRequestWrapper (Anfrage, Antwort, this.servletContext); SessionRepositoryResponsewrapper WrapedResponse = new SessionRepositoryResponseWrapper (WrapedRequest, Antwort); HttpServletRequest StrategyRequest = this.httpSsionSsionStrategy.WrapRequest (WrapedRequest, WrappedResponse); HttpServletResponse StrategyResponse = this.httpSessionStrategy .WrapResponse (WrapedRequest, WrapedResponse); Versuchen Sie es mit { /** die benutzerdefinierte Anforderung und Antwort an die Kette. Stellen Sie sich vor, der Federsitzungsfilter befindet sich an der ersten der Filterkette, dann sind die nachfolgenden Filter sowie die Anforderung und Antwort, die durch Erreichen der letzten Kontrollschicht erhalten werden, sie passen sie an? **/ filterchain.dofilter (StrategyRequest, StrategyResponse); } endlich {WrapedRequest.CommitSession (); }} public void setServletContext (servletContext servletContext) {this.servletContext = servletContext; } / ** Dies ist die umgeschriebene Klasse der Servlet -Antwort* / private endgültige Klasse SessionRepositoryResponsewrapper erweitert die On -CommittResponsewrapper {private endgültige SessionRepositoryRequestWrapper -Anforderung; SessionRepositoryResponseWrapper (SessionRepositoryRequestWrapper -Anforderung, httpServletResponse -Antwort) {Super (Antwort); if (request == null) {neue illegalArgumentException werfen ("Anfrage kann nicht null sein"); } this.Request = Anfrage; } /** Dieser Schritt soll die Sitzung in den Speicherbehälter fortsetzen. Wir können die Betriebsmethode der Sitzung in einer Steuerungsschicht mehrmals aufrufen. Wenn jeder Betrieb der Sitzung in den Speicherbehälter anhält, hat dies definitiv eine Leistungswirkung. Zum Beispiel können wir die gesamte Steuerungsschicht ausführen, und die Antwort gibt Informationen an den Browser zurück, und die Sitzung wird nur bestehen, wenn die Antwort die Informationen an den Browser zurückgibt. **/ @Override protected void onresponSecommitt () {this.Request.CommitSession (); }} /** Die Anforderung Umschreiben der Frühlingssitzung ist fast die wichtigste Umschreiben-Klasse. Es geschrieben Methoden wie GetSession, Sitzung und andere Methoden sowie Klassen */ private endgültige Klassen -SessionRepositoryRequestWrapper erweitert HttpServletRequestWrapper {private boolean RequestedSessionIdvalid; privat boolean beantragte messessioninvalidated; private endgültige HTTPServletResponse -Antwort; private final servletContext servletContext; private sessionRepositoryRequestWrapper (httpServletRequest -Anforderung, httpServletResponse -Antwort, ServletContext ServletContext) {Super (Request); this.Response = Antwort; this.servletContext = servletContext; } /** * verwendet die httpSessionStrategy, um die Sitzungs -ID in die Antwort zu schreiben und die Sitzung zu bestehen. */ private void commitSession () {httpSessionWrapper WrapedSession = getCurrentSession (); if (WrapedSession == NULL) {// Session Abgelaufen, löschen Cookies oder Header if (isinvalidateClientSession ()) {sesepositoryFilter.this.httpSsionSsionStrategy .oninvalidatessession (this.response); }} else {s session = WrapedSession.getSession (); SessionRepositoryFilter.this.SessionRepository.save (Sitzung); If (! }}} @Suppresswarnings ("Deaktiviert") private httpSessionWrapper getCurrentSession () {return (httpSessionWrapper) getAtTribute (current_session_attr); } private void setCurrentSession (httpSessionWrapper currentSession) {if (currentSession == null) {removeAttribute (current_session_attr); } else {setAttribute (current_Session_attr, currentSession); }} @SuppressWarnings ("unbenutzt") public StringSeSessionID () {httpSession Session = getSession (false); if (Session == NULL) {Neue IllegalStateException werfen ("Die Sitzungs -ID kann nicht geändert werden. Diese Anfrage ist keine Sitzung zugeordnet."); } // Sesselige Sitzungsattribute in Fall Implementierung Lazy lädt sie map <string, Object> attrs = new Hashmap <String, Object> (); Enumeration <string> iattrnames = session.getAttributenames (); while (iattrnames.hasmoreElements ()) {String attrName = iattrnames.NextElement (); Object value = session.getAttribute (attrName); attr.put (attrname, value); } SessionRepositoryFilter.this.SessionRepository.delete (Session.getId ()); HttpSessionWrapper Original = GetCurrentSession (); setCurrentSession (null); HttpSessionSwrapper newsion = getSession (); Original.SetSession (Newsions.GetSession ()); Newssions.SetMaxinActiveInterval (Session.getMaxinActiveInterVal ()); für (map.entry <String, Objekt> attr: attr.entrySet ()) {String attrname = attr.getKey (); Objekt attrValue = attr.getValue (); Newssion.Setattribute (Attrname, AttrValue); } return Newsion.getId (); } // Bestimmen Sie, ob die Sitzung gültig ist. S session = sessionId == null? NULL: GETSSETS (SessionID); return isRequestedSessionIdvalid (Sitzung); } return this.RequestedSessionidvalid; · } return this.RequestedSessionidvalid; · } private s GetSession (String SessionID) {// Sitzung aus dem Sitzungsspeicher Container basierend auf SessionID s session = sessionRepositoryFilter.this.SessionRepository .GetSession (SessionID); if (session == null) {return null; } // Die letzte Zugriffszeit der Sitzung festlegen, um zu verhindern, dass die Sitzung abgelaufen ist. Rückgabesitzung; } /** Ist diese Methode sehr vertraut? Es gibt auch eine GetSession () unten, um vertrauter zu sein. Das ist richtig. Nehmen Sie einfach die Sitzungsmethode hier wieder ein **/@Override public httpSessionWrapper GetSession (boolean create) {// schnelle Sitzung erhalten, die als Beziehung zwischen Cache erster Ebene und Cache der zweiten Ebene verstanden werden kann. if (currentSession! = null) {return screntSession; } // SessionID von httpSsionStret appelledSessionId = getRequestedSessionID () erhalten; if (requestedSessionId! = null && getAtTribute (Invaly_Session_id_attr) == NULL) {// Session aus dem Speichercontainer abrufen und das aktuelle Initialisierungsattribut s session = getSession (forderedSessionID) festlegen; if (session! currentSession = new httpSessionWrapper (Sitzung, getServletContext ()); CurrentSession.setNew (falsch); setCurrentSession (Strömung); Return StrourSession; } else {if (session_logger.isdebugenabled ()) {session_logger.debug ("Keine Sitzung gefunden durch ID: Caching -Ergebnis für getSession (false) für diese httpServletRequest."); } setAttribute (Invaly_Session_id_attr, "true"); }} if (! create) {return null; } if (session_logger.isdebugenabled ()) {session_logger.debug ("Eine neue Sitzung wurde erstellt. Um Ihnen zu helfen, bei der Sitzung zu beheben, dass wir eine Stacktrace erstellt haben (dies ist kein Fehler). Fehler)")); } // Wenn der Browser oder ein anderer HTTP -Besucher zum ersten Mal auf den Server zugreift, erstellen Sie eine neue Sitzungssitzung für ihn = sessionRepositoryFilter.this.SessionRepository.Createsession (); Session.setLastAccessTime (System.currentTimemillis ()); currentSession = new httpSessionWrapper (Sitzung, getServletContext ()); setCurrentSession (Strömung); Return StrourSession; } @Override public ServletContext getServletContext () {if (this.servletContext! = Null) {return this.servletContext; } // Servlet 3.0+ return Super.getServletContext (); } @Override public httpSessionWrapper getSession () {return getSession (true); } @Override public String getRequestedSessionID () {return SessionRepositoryFilter.this.httpSsionSsionStrategy .GetRequestedSessionID (this); } / ** Umschreiben Sie die Klasse von httpSession* / private endgültige Klasse httpSessionWrapper erweitert expiringSessionhtpSession <s> {httpSessionWrapper (s Sitzung, ServletContext ServletContext) {Super (Session, ServletContext); } @Override public void Invalidate () {Super.invalidate (); SessionRepositoryRequestWrapper setCurrentSession (null); SessionRepositoryFilter.this.SessionRepository.Delete (getId ()); }}}}Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels über die Einführung der Frühlingssitzung und die Quellcode-Analyse der Implementierungsprinzipien. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen!