VorwortDas vollständigste UML-Klassendiagramm von Tomcat Tomcat-Anforderungsverarbeitungsprozess: Wenn das Connector-Objekt erstellt wird, wird der ProtocolHandler von Http11NioProtocol erstellt. In der startInteral-Methode von Connector wird AbstractProtocol gestartet. AbstractProtocol startet NioEndPoint, um auf die Anfrage des Clients zu hören. Nachdem EndPoint die Anfrage des Clients empfangen hat, übergibt es sie an Container, um die Anfrage zu verarbeiten. Alle Container, die eine Anfrage ausgehend von der Engine durchläuft, enthalten ein Verantwortungskettenmuster. Jedes Mal, wenn ein Container durchläuft, wird die Verantwortungskette dieses Containers aufgerufen, um die Anfrage zu verarbeiten. 1. EndpunktDie Standardimplementierung von EndPoint ist NioEndPoint. NioEndPoint hat vier interne Klassen: Poller, Acceptor, PollerEvent, SocketProcessor und NioSocketWrapper. (1) Der Acceptor ist für die Überwachung der Benutzeranforderungen verantwortlich. Nach der Überwachung der Benutzeranforderungen ruft er (2) Der Poller-Thread durchläuft weiterhin die Ereignisse, die verarbeitet werden können (Nettys Selestor). Wenn er das Ereignis findet, das verarbeitet werden muss, ruft er (3) PollerEvent erbt von der Schnittstelle Runnable. Wenn in seiner Run-Methode das Ereignis von PollerEvent darin besteht, OP_REGISTER zu registrieren, wird der aktuelle Socket beim Poller-Selektor registriert. öffentliche Leere ausführen() { wenn (interestOps == OP_REGISTER) { versuchen { //Kerncode endlich gefunden! ! ! ! ! // Wenn das Ereignis eine Registrierung ist, registrieren Sie den aktuellen NioSocketChannel beim Selector des Pollers. socket.getIOChannel().register( socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper); } Fang (Ausnahme x) { log.error(sm.getString("endpoint.nio.registerFail"), x); } } anders { endgültiger SelectionKey-Schlüssel = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); versuchen { wenn (Schlüssel == null) { // Der Schlüssel wurde gelöscht (zB durch Socket-Schließung) // und aus dem Selektor entfernt, während dieser // verarbeitet. Zählen Sie an dieser Stelle die Verbindungen herunter // da der Countdown nicht abgelaufen ist, wenn der Socket // geschlossen. // Wenn SelectionKey abgebrochen wird, muss der Verbindungszähler des EndPoint, der dem SelectionKey entspricht, um eins reduziert werden socket.socketWrapper.getEndpoint().countDownConnection(); ((NioSocketWrapper) socket.socketWrapper).geschlossen = true; } anders { endgültiger NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment(); wenn (socketWrapper != null) { //Wir registrieren zunächst den Schlüssel und setzen den Fairnesszähler zurück. int ops = key.interestOps() | InteresseOps; socketWrapper.interestOps(ops); Schlüssel.InteresseOps(ops); } anders { socket.getPoller().cancelledKey(Schlüssel); } } } Fang (CancelledKeyException ckx) { versuchen { socket.getPoller().cancelledKey(Schlüssel); } catch (Ausnahme ignorieren) { } } } } (4) Der Poller-Thread führt // Holen Sie sich den Iterator der ausgewählten Schlüssel Iterator<SelectionKey> iterator = Schlüsselanzahl > 0? selector.selectedKeys().iterator() : null; // Alle SelectionKeys durchlaufen und verarbeiten, während (Iterator != null und iterator.hasNext()) { Auswahlschlüssel sk = iterator.next(); iterator.entfernen(); NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment(); // Anhang kann null sein, wenn ein anderer Thread aufgerufen hat // abgebrochenerSchlüssel() // Wenn ein Anhang vorhanden ist, verarbeite ihn if (socketWrapper != null) { //Ereignisse verarbeiten processKey(sk, socketWrapper); } } processKey verarbeitet SelectionKey. Wenn der aktuelle Poller geschlossen wird, wird der Schlüssel gelöscht. Wenn im Kanal, der SelectionKey entspricht, ein Leseereignis auftritt, wird AbatractEndPoint.processSocket aufgerufen, um den Lesevorgang geschützter void processKey(SelectionKey sk, NioSocketWrapper-Anhang) { versuchen { if (schließen) { //Wenn Poller geschlossen ist, brechen Sie den Schlüssel ab abgebrochener Schlüssel (sk); } sonst wenn (sk.isValid() && Anhang != null) { wenn (sk.isReadable() || sk.isWritable()) { if (attachment.getSendfileData() != null) { processSendfile(sk, Anhang, false); } anders { unreg(sk, Anhang, sk.readyOps()); Boolescher Wert closeSocket = false; // Lesen geht vor Schreiben // Lesen ist besser als Schreiben // Wenn der Kanal, der dem SelectionKey entspricht, zum Lesen bereit ist // dann lese den NioSocketWrapper if (sk.isReadable()) { wenn (!processSocket(attachment, SocketEvent.OPEN_READ, true)) { : Schließen Sie den Socket nicht. } } // Wenn der Kanal, der dem SelectionKey entspricht, zum Schreiben bereit ist // In NioSocketWrapper schreiben if (!closeSocket && sk.isWritable()) { wenn (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) { : Schließen Sie den Socket nicht. } } if (Socket schließen) { //Wenn es bereits geschlossen ist, brechen Sie den Schlüssel ab abgebrochener Schlüssel (sk); } } } } Die Methode AbatractEndPoint.processSocket ruft zuerst die Klasse SocketProcessor aus dem Cache ab. Wenn im Cache kein SocketProcessor vorhanden ist, wird einer erstellt. Die Schnittstelle SocketProcessorBase entspricht NioEndPoint.SocketProcessor, also Worker. Legen Sie die entsprechende SocketProcessor-Klasse zur Ausführung in den Thread-Pool. öffentlicher boolescher ProzessSocket(SocketWrapperBase<S> socketWrapper, SocketEvent-Ereignis, Boolescher Dispatch) { // Den Socket-Prozessor abrufen // Der Connector hat das Protokoll im Konstruktor angegeben: org.apache.coyote.http11.Http11NioProtocol. SocketProcessorBase<S> sc = processorCache.pop(); wenn (sc == null) { // Wenn nicht, erstellen Sie einen Socket-Handler. Geben Sie beim Erstellen SocketWrapper und Socket-Ereignisse an. sc = createSocketProcessor(socketWrapper, Ereignis); } anders { sc.reset(socketWrapper, Ereignis); } //Die Socket-Verarbeitung wird an den Thread-Pool übergeben. Executor Executor = getExecutor(); wenn (Dispatch und Executor != null) { Executor.execute(sc); } anders { sc.run(); } (5) NioEndPoint.NioSocketWrapper ist die Kapselungsklasse und Erweiterungsklasse von Socket, die Socket mit anderen Objekten verknüpft. öffentliche statische Klasse NioSocketWrapper erweitert SocketWrapperBase<NioChannel> { privater endgültiger NioSelectorPool-Pool; privater Poller poller = null; // Polling-Poller private int InteressenOps = 0; privater CountDownLatch readLatch = null; privater CountDownLatch writeLatch = null; private flüchtige SendfileData sendfileData = null; privates flüchtiges langes letztes Lesen = System.currentTimeMillis(); privates flüchtiges langes letztes Schreiben = letztes Lesen; privater flüchtiger Boolescher Wert geschlossen = false; (6) NioEndPoint.SocketProcessor (Worker) erbt die Runnable-Schnittstelle und ist für die Verarbeitung verschiedener Ereignisse des Sockets verantwortlich. Leseereignisse, Schreibereignisse, Stoppzeit, Timeout-Ereignisse, Trennungsereignisse, Fehlerzeit, Verbindungsfehlerereignisse. Die doRun-Methode von SocketProcessor wird gemäß SocketState verarbeitet. Wenn SocketState STOP, DISCONNECT oder ERROR ist, wird es geschlossen. Das Selector-Ereignis, das SocketWrapperBase entspricht, wird vom angegebenen Handler-Prozessor verarbeitet. @Überschreiben geschützt void doRun() { NioChannel-Socket = socketWrapper.getSocket(); SelectionKey-Schlüssel = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); versuchen { int Handshake = -1; versuchen { wenn (Schlüssel != null) { wenn (socket.isHandshakeComplete()) { // Unabhängig davon, ob der Handshake erfolgreich war und kein TLS-Handshake (verschlüsselt) erforderlich ist, lassen Sie den Prozessor die Kombination aus Socket und Ereignis verarbeiten. Handshake = 0; } sonst wenn (Ereignis == SocketEvent.STOP || Ereignis == SocketEvent.DISCONNECT || Ereignis == SocketEvent.ERROR) { // Wenn der TLS-Handshake nicht abgeschlossen werden kann, wird dies als ein TLS-Handshake-Fehler betrachtet. Handshake = -1; } anders { Handshake = Socket.Handshake (Schlüssel.ist lesbar (), Schlüssel.ist schreibbar (); // Der Handshake-Prozess liest/schreibt von/in die // Socket. Status kann daher einmal OPEN_WRITE sein // der Handshake wird abgeschlossen. Der Handshake // passiert, wenn der Socket geöffnet wird, also der Status // muss nach Abschluss immer OPEN_READ sein. // Es ist in Ordnung, dies immer festzulegen, da es nur verwendet wird, wenn // der Handshake ist abgeschlossen. // Beim Handshake zum Lesen/Schreiben vom/zum Socket sollte der Status OPEN_WRITE sein, sobald der Handshake abgeschlossen ist. // Der Handshake findet statt, wenn der Socket geöffnet wird, daher muss der Status nach Abschluss immer OPEN_READ sein. // Es ist in Ordnung, diese Option immer festzulegen, da sie nur verwendet wird, wenn der Handshake abgeschlossen ist. Ereignis = SocketEvent.OPEN_READ; } } } Fang (IOException x) { Handshake = -1; if (log.isDebugEnabled()) log.debug("Fehler beim SSL-Handshake", x); } Fang (CancelledKeyException ckx) { Handshake = -1; } wenn (Handshake == 0) { SocketState-Status = SocketState.OPEN; // Verarbeite die Anfrage von diesem Socket wenn (Ereignis == null) { // Rufen Sie den Handler zur Verarbeitung auf. // Der Standard-Handler von NioEndPoint ist Http11 // Der Handler hier ist AbstractProtocol.ConnectionHandler // Die Einstellungsmethode dieses Handlers ist: // Legen Sie zunächst im Konstruktor der Connector-Klasse den Standard-ProtocolHandler auf org.apache.coyote.http11.Http11NioProtocol fest. // Die Handler-Klasse ConnectionHandler wird im Konstruktor von AbstractHttp11Protocol erstellt Status = getHandler().Prozess(socketWrapper, SocketEvent.OPEN_READ); } anders { Status = getHandler().Prozess(socketWrapper, Ereignis); } // Wenn der zurückgegebene Status SocketState ist, schließe die Verbindung if (state == SocketState.CLOSED) { schließen (Buchse, Schlüssel); } } sonst wenn (Handshake == -1) { getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL); schließen (Buchse, Schlüssel); } sonst wenn (Handshake == Auswahlschlüssel.OP_READ) { // Wenn es SelectionKey.OP_READ ist, also ein Leseereignis, setzen Sie die OP_READ-Zeit auf socketWrapper socketWrapper.registerReadInterest(); } sonst wenn (Handshake == Auswahlschlüssel.OP_WRITE) { // Wenn es SelectionKey.OP_WRITE ist, also ein Leseereignis, setzen Sie das OP_WRITE-Ereignis auf socketWrapper socketWrapper.registerWriteInterest(); } 2. Verbindungshandler(1) ConnectionHandler wird verwendet, um den entsprechenden Engine-Prozessor basierend auf der Socket-Verbindung zu finden. Oben ist die doRun-Methode von SocketProcessor, die geschützte statische Klasse ConnectionHandler<S> implementiert AbstractEndpoint.Handler<S> { privates endgültiges AbstractProtocol<S>-Proto; private final RequestGroupInfo global = neue RequestGroupInfo(); private final AtomicLong registerCount = neues AtomicLong(0); // Schließlich wurde diese Sammlung gefunden und eine Verbindung zwischen dem Socket und dem Prozessor hergestellt. // Jeder gültige Link wird hier zwischengespeichert, um eine Verbindung herzustellen und eine geeignete Prozessorimplementierung für die Anforderungsverarbeitung auszuwählen. private finale Map<S, Prozessor>-Verbindungen = neue ConcurrentHashMap<>(); // Wiederverwertbarer Prozessorstapel private final RecycledProcessors recycledProcessors = new RecycledProcessors(this); @Überschreiben öffentlicher SocketState-Prozess (SocketWrapperBase<S>-Wrapper, SocketEvent-Status) { wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.process", wrapper.getSocket(), status)); } wenn (Wrapper == null) { // Wrapper == null bedeutet, dass der Socket geschlossen wurde und daher keine Aktion erforderlich ist. SocketState.CLOSED zurückgeben; } //Holen Sie sich das Socket-Objekt S im Wrapper socket = wrapper.getSocket(); //Den zum Sockel passenden Prozessor aus dem Map-Puffer holen. Prozessor Prozessor = Verbindungen.get(Socket); wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.connectionsGet", Prozessor, Sockel)); } // Timeouts werden auf einem dedizierten Thread berechnet und dann // versendet. Aufgrund von Verzögerungen im Versandprozess ist die // Timeout ist möglicherweise nicht mehr erforderlich. Überprüfen Sie hier und vermeiden Sie // unnötige Verarbeitung. // Das Timeout wird auf einem dedizierten Thread berechnet und dann geplant. // Aufgrund von Verzögerungen im Planungsprozess ist das Timeout möglicherweise nicht mehr erforderlich. Klicken Sie hier, um unnötige Verarbeitung zu vermeiden. wenn (SocketEvent.TIMEOUT == status && (Prozessor == null || !processor.isAsync() und !processor.isUpgrade() || Prozessor.isAsync() && !Prozessor.checkAsyncTimeoutGeneration())) { // Dies ist praktisch ein NO-OP SocketState.OPEN zurückgeben; } // Wenn der Map-Cache einen Prozessor hat, der mit dem Socket verknüpft ist if (processor != null) { // Stellen Sie sicher, dass kein asynchrones Timeout ausgelöst wird // Stellen Sie sicher, dass kein asynchrones Timeout ausgelöst wird getProtocol().removeWaitingProcessor(processor); } sonst wenn (status == SocketEvent.DISCONNECT || status == SocketEvent.ERROR) { // Nichts zu tun. Endpunkt hat eine Schließung angefordert und es gibt keine // Es ist kein Prozessor mehr mit diesem Sockel verbunden. // Das SocketEvent-Ereignis ist geschlossen oder die SocketEvent-Zeit ist falsch. Zu diesem Zeitpunkt ist kein Vorgang erforderlich. // Der Endpunkt benötigt ein GESCHLOSSEN-Signal und es besteht keine Verbindung mehr, die mit diesem Socket verknüpft ist. return SocketState.CLOSED; } ContainerThreadMarker.set(); versuchen { // Der Map-Cache enthält nicht den Prozessor, der diesem Socket zugeordnet ist, if (processor == null) { Zeichenfolge ausgehandeltesProtokoll = Wrapper.getNegotiatedProtocol(); // OpenSSL gibt normalerweise null zurück, während JSSE normalerweise // gibt "" zurück, wenn kein Protokoll ausgehandelt wurde // OpenSSL gibt normalerweise null zurück, während JSSE normalerweise "" zurückgibt, wenn kein Protokoll ausgehandelt wurde wenn (negotiatedProtocol != null und negotiationProtocol.length() > 0) { // Holen Sie sich das Verhandlungsprotokoll UpgradeProtocol upgradeProtocol = getProtocol().getNegotiatedProtocol(negotiatedProtocol); wenn (upgradeProtocol != null) { // Das Upgrade-Protokoll ist leer. Prozessor = upgradeProtocol.getProcessor(Wrapper, getProtocol().getAdapter()); wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", Prozessor)); } } sonst wenn (negotiatedProtocol.equals("http/1.1")) { // Das Standardprotokoll wurde explizit ausgehandelt. // Besorgen Sie sich unten einen Prozessor. } anders { // ZU TUN: // Der ALPN-Rückruf von OpenSSL 1.0.2 unterstützt nicht // Der Handshake schlägt mit einem Fehler fehl, wenn nein // Protokoll kann ausgehandelt werden. Daher müssen wir // Die Verbindung schlägt hier fehl. Sobald dies behoben ist, // Ersetzen Sie den folgenden Code durch den auskommentierten // blockieren. wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.negotiatedProcessor.fail", ausgehandeltesProtokoll)); } gibt SocketState.CLOSED zurück; /* * Um den obigen Code zu ersetzen, sobald OpenSSL 1.1.0 * gebraucht. // Prozessor konnte nicht erstellt werden. Dies ist ein Fehler. neue IllegalStateException werfen(sm.getString( "abstractConnectionHandler.negotiatedProcessor.fail", ausgehandeltesProtokoll)); */ } } } // Nach den obigen Vorgängen ist der Prozessor immer noch null. if (Prozessor == null) { // Holen Sie sich den Prozessor aus den wiederverwertbaren Prozessoren von recycledProcessors Prozessor = recycelteProzessoren.pop(); wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.processorPop", Prozessor)); } } if (Prozessor == null) { // Einen Prozessor erstellen processor = getProtocol().createProcessor(); Register (Prozessor); wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", Prozessor)); } } Prozessor.setSslSupport( wrapper.getSslSupport(getProtocol().getClientCertProvider())); // Den Sockel dem Prozessor zuordnen. Verbindungen.put(Socket, Prozessor); SocketState-Status = SocketState.GESCHLOSSEN; Tun { // Rufen Sie die Prozessmethode des Prozessors auf. Zustand = Prozessor.Prozess(Wrapper, Status); // Die Prozessmethode des Prozessors gibt den Upgrade-Status zurück, wenn (Status == SocketState.UPGRADING) { // Den HTTP-Upgrade-Handler abrufen // HTTP-Upgrade-Handle abrufen UpgradeToken upgradeToken = processor.getUpgradeToken(); // Restliche Eingabe abrufen // Verbleibende Eingabe abrufen ByteBuffer leftOverInput = processor.getLeftoverInput(); if (upgradeToken == null) { // Direkte HTTP/2-Verbindung vorausgesetzt UpgradeProtocol upgradeProtocol = getProtocol().getUpgradeProtocol("h2c"); wenn (upgradeProtocol != null) { // Den Http11-Prozessor zur Wiederverwendung freigeben Freigabe (Prozessor); // Den Upgrade-Prozessor erstellen Prozessor = upgradeProtocol.getProcessor(Wrapper, getProtocol().getAdapter()); Wrapper.unRead(leftOverInput); // Mit dem Prozessor über die Verbindung verknüpfen Verbindungen.put(Socket, Prozessor); } anders { wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString( "abstractConnectionHandler.negotiatedProcessor.fail", "h2c")); } //Schleife verlassen und entsprechende Bereinigung auslösen Zustand = SocketState.GESCHLOSSEN; } } anders { HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler(); // Den Http11-Prozessor zur Wiederverwendung freigeben Freigabe (Prozessor); // Den Upgrade-Prozessor erstellen Prozessor = getProtocol().createUpgradeProcessor(Wrapper, UpgradeToken); wenn (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.upgradeCreate", Prozessor, Wrapper)); } wrapper.unRead(leftOverInput); // Mit dem Prozessor über die Verbindung verknüpfen Verbindungen.put(Socket, Prozessor); // Initialisieren Sie den Upgrade-Handler (der möglicherweise auslöst // einige IO mit dem neuen Protokoll, weshalb die Zeilen //oben sind erforderlich) // Dieser Cast sollte sicher sein. Wenn er fehlschlägt, wird der Fehler // Die Handhabung des umgebenden Try/Catch wird erledigt // Es. if (upgradeToken.getInstanceManager() == null) { httpUpgradeHandler.init((WebConnection) Prozessor); } anders { ClassLoader oldCL = upgradeToken.getContextBind().bind(false, null); versuchen { httpUpgradeHandler.init((WebConnection) Prozessor); Endlich upgradeToken.getContextBind().unbind(false, oldCL); } } } } } während (Status == SocketState.UPGRADING); (2) Am Beispiel des Http11-Protokolls wird Http11Processor ausgeführt. Die übergeordnete Klasse von Http11Processor, AbstractProcessorLight, implementiert die Prozessmethode. Der Prozess ruft die Service-Vorlagenmethode auf, die von Http11Processor implementiert wird. Die wichtigste Operation der Servicemethode ist die Ausführung @Überschreiben öffentlicher SocketState-Dienst (SocketWrapperBase<?> socketWrapper) wirft IOException { // n Zeilen oben werden ausgelassen // Rufen Sie die Servicemethode von Coyote auf getAdapter().service(request, response); // Die folgenden n Zeilen werden weggelassen 3. KojoteDenken Sie daran, dass CoyoteAdapter in der initInternal-Methode von Connector erstellt wird. @Überschreiben öffentlicher SocketState-Dienst (SocketWrapperBase<?> socketWrapper) wirft IOException { // n Zeilen oben werden ausgelassen // Rufen Sie die Servicemethode von Coyote auf getAdapter().service(request, response); // Die folgenden n Zeilen werden weggelassen Die Funktion von Coyote besteht darin, coyote.Request und coyote.Rsponse in HttpServletRequest und HttpServletRsponse umzuwandeln. Da sich der Connector während der Initialisierung selbst in den CoyoteAdapter einfügt, kann der Dienst direkt über @Überschreiben öffentlicher SocketState-Dienst (SocketWrapperBase<?> socketWrapper) wirft IOException { // n Zeilen oben werden ausgelassen // Rufen Sie die Servicemethode von Coyote auf getAdapter().service(request, response); // Die folgenden n Zeilen werden weggelassen 4. Muster der Container-VerantwortungsketteAls nächstes folgt das Verantwortungskettenmodell, das bei StandardEngine beginnt. Führen Sie zunächst den Verantwortungskettenmodus von StandardEngine aus, um die entsprechende Engine zu finden. Die entsprechende Engine findet dann den entsprechenden Kontext über den Verantwortungskettenmodus, bis StandardWrapperValve gefunden wird. Abschließend wird die Invoke-Methode von StandardWrapperValve ausgeführt. Überprüfen Sie zunächst, ob Context und Wrapper nicht verfügbar sind. Wenn sie verfügbar sind und Servelt nicht initialisiert wurde, führen Sie den Initialisierungsvorgang aus. Im Single-Thread-Modus wird der zuvor erstellte Servelt direkt zurückgegeben. Im Multi-Thread-Modus wird zuerst ein Servelt-Objekt erstellt und zurückgegeben. @Überschreiben öffentliches Finale void invoke (Anfrage Anfrage, Antwort Antwort) wirft IOException, ServletException { // Initialisieren Sie die benötigten lokalen Variablen boolean unavailable = false; Wurfbar, Wurfbar = null; // Dies sollte ein Anforderungsattribut sein … lange t1 = System.currentTimeMillis(); // Atomare Klasse AtomicInteger, CAS-Operation, die die Anzahl der Anfragen angibt. requestCount.incrementAndGet(); StandardWrapper-Wrapper = (StandardWrapper) getContainer(); Servlet-Servlet = null; Kontext Kontext = (Kontext) wrapper.getParent(); // Überprüfen Sie, ob die aktuelle Context-Anwendung als nicht verfügbar markiert wurde if (!context.getState().isAvailable()) { //Wenn die aktuelle Anwendung nicht verfügbar ist, melden Sie einen 503-Fehler. Antwort.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable")); nicht verfügbar = wahr; } // Prüfen, ob der Servelt als nicht verfügbar markiert ist, if (!unavailable && wrapper.isUnavailable()) { container.getLogger().info(sm.getString("standardWrapper.istNichtverfügbar", wrapper.getName())); lange verfügbar = Wrapper.getAvailable(); if ((verfügbar > 0L) && (verfügbar < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", verfügbar); Antwort.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.istNichtverfügbar", wrapper.getName())); } sonst wenn (verfügbar == Long.MAX_VALUE) { Antwort.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName())); } nicht verfügbar = wahr; } //Servelt wird beim ersten Aufruf initialisiert try { wenn (!nicht verfügbar) { // Wenn Servelt zu diesem Zeitpunkt noch nicht initialisiert wurde, weisen Sie eine Servelt-Instanz zur Bearbeitung der Anforderung zu. servlet = Wrapper.Zuweisen(); } /// Code auslassen........................................... // // Erstellen Sie eine Filterkette für die Anfrage. Nachdem die Filterkette ausgeführt wurde, Servelt Anwendungsfilterkette Filterkette = ApplicationFilterFactory.createFilterChain(Anfrage, Wrapper, Servlet); // Rufe die Filterkette für diese Anfrage auf // HINWEIS: Dies ruft auch die service()-Methode des Servlets auf versuchen { wenn ((servlet != null) und (filterChain != null)) { // Bei Bedarf die Ausgabe schlucken wenn (Kontext.getSwallowOutput()) { versuchen { SystemLogHandler.startCapture(); wenn (request.isAsyncDispatching()) { request.getAsyncContextInternal().doInternalDispatch(); } anders { //Filterkette aufrufen filterChain.doFilter(request.getRequest(), Antwort.getResponse()); } /// Code auslassen........................................... Dies ist das Ende dieses Artikels über die Analyse des Tomcat-Quellcodes sowie Webanforderungen und -verarbeitung. Weitere Inhalte zu Tomcats Webanforderungen und -verarbeitung finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: So beheben Sie die durch MySQL DDL verursachte Synchronisierungsverzögerung
>>: Erfahren Sie in einem Artikel mehr über JavaScript-Closure-Funktionen
Treemaps dienen vor allem der Visualisierung baum...
Vorwort: Ich wollte schon immer wissen, wie eine ...
Inhaltsverzeichnis Übergeordnete Komponente „list...
Dieser Artikel beschreibt eine native JS-Implemen...
Inhaltsverzeichnis Klassenkomponente Funktionale ...
DOM-Konzepte DOM: Dokumentobjektmodell: Das Dokum...
Inhaltsverzeichnis 1. Ändern Sie die app.vue-Seit...
Im vorherigen Artikel – Der Charme einer Zeile CS...
Vorwort: Letzten Sonntag bat mich ein Senior, ihm...
In letzter Zeit habe ich jeden Tag an meinen Absch...
1. Szenariobeschreibung: Unsere Umgebung verwende...
Unten beginnt der Haupttext. 123WORDPRESS.COM Her...
Verwenden Sie „onInput(event)“, um festzustellen,...
Inhaltsverzeichnis Geschäftsanforderungen: Lösung...
Inhaltsverzeichnis 1. Map akzeptiert jeden Schlüs...