2015-09-13 12 views
6

Ich frage mich, wie funktioniert Tomcat Bootstrap meine App auf Spring MVC?Wie bootet Tomcat die App ohne web.xml?

Ich habe einen Initialisierer:

public class AppInitializer implements WebApplicationInitializer { 
    @Override 
    public void onStartup(ServletContext container) { 
     AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext(); 
     rootCtx.register(AppConfig.class); 
     container.addListener(new ContextLoaderListener(rootCtx)); 
     AnnotationConfigWebApplicationContext dispatcherCtx = new AnnotationConfigWebApplicationContext(); 
     dispatcherCtx.register(FreeMarkerWebConfig.class); 
     ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherCtx)); 
     dispatcher.setLoadOnStartup(1); 
     dispatcher.addMapping("/"); 
    } 
} 

Ich weiß, warum wir web.xml brauchen und wie Tomcat verwendet es die App Bootstrap. Aber ich verstehe nicht, wie Tomcat wissen, welches Servlet es verwenden sollte, um die Anwendung zu starten, wenn es keine xml Dateien gibt, aber nur AppAppInitializer?

Abhängigkeiten

<!-- spring mvc --> 
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-webmvc</artifactId> 
    <version>4.2.1.RELEASE</version> 
</dependency> 
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context-support</artifactId> 
    <version>4.2.1.RELEASE</version> 
</dependency> 
<!-- servlet --> 
<dependency> 
    <groupId>javax.servlet</groupId> 
    <artifactId>javax.servlet-api</artifactId> 
    <version>3.0.1</version> 
</dependency> 

... 

fand ich diese Klasse in Federkern SpringServletContainerInitializer. Stimmt es, dass Tomcat es zum Bootstrap meiner App verwendet?

http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContainerInitializer.html?is-external=true

Antwort

13

Servlet 3.0 hat einen Pluggability-Mechanismus hinzugefügt. Wie es funktioniert, ist das, wenn Ihre App geladen wird, durchsucht es den Klassenpfad für META-INF/services und sucht nach einer Datei mit Name javax.servlet.ServletContainerInitializer. Dort sollte der Implementierer den Namen der Implementierung haben, wo der Servlet-Container ihn laden kann. Sie können diese Datei im spring-web Glas sehen.Es listet org.springframework.web.SpringServletContainerInitializer als die Implementierung des Initialisierers auf.

Wie der Spring-Initialisierer funktioniert, ist, dass es alle Implementierungen (auf dem Klassenpfad) von WebApplicationInializer vom Servlet-Container übergeben wird. Wie kann der Servlet-Container diese Implementierungen bestehen? Wenn man sich die source code for the inializer betrachten, werden Sie

@HandlesTypes(WebApplicationInitializer.class) 
public class SpringServletContainerInitializer implements ServletContainerInitializer { 

Es ist die @HandlesType Anmerkung sehen. Alle Klassen und sogar Anmerkungen [] in den @HandlesTypes aufgeführt werden erhalten durch die Servlet-Container und an die SevletContainerInitializer durch das einzelnen Callback-Methode Argument

void onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx) 

Das Set Argument enthält alle nehmen die Implementationen, die während des Scannens vom Servlet-Container aufgenommen wurden. Sie können den Quellcode durchsehen, um zu sehen, was Spring mit diesen Implementierungen macht. Es ruft im Grunde nur die onStartup aller Inializer, in der ServletContext übergeben.


[] - Das ist ein wenig unklar klang (und erklären es oben hätte auf einer Tangente ein bisschen weg gegangen), so werde ich es nur als Statist hier posten.

Stellen Sie sich vor der @HandlesType statt

@HandlesTypes({WebApplicationInitializer.class, Controller.class}) 
public class SpringServletContainerInitializer implements ServletContainerInitializer { 

war Das bedeutet, dass der Servlet-Container auch für Klassen mit @Controller kommentierte scannt, und auch diejenigen, auf die onStartup des Frühlings initializer passieren.

+1

Danke. Jetzt weiß ich, wie es funktioniert. – Finkelson

1

es mit einer Tatsache verbunden ist, arbeitet das Servlet 3.0 API ohne web.xml. Also, es ist kein Spring-Feature.

Mehr Infos hier: https://blogs.oracle.com/swchan/entry/servlet_3_0_annotations

JSR 315: JavaTM Servlet 3.0-Spezifikation: https://jcp.org/en/jsr/detail?id=315

UPD:

Frühling WebApplicationInitializer eine programmatische Art und Weise stellt die Frühlings-DispatcherServlet und Context in Servlets zu konfigurieren 3.0+ konforme Servlet-Container, anstatt diese Konfiguration über eine web.xml-Datei hinzuzufügen.

Die Antwort ist die ServletContainerInitializer-Schnittstelle, die mit der Servlet 3.0-Spezifikation eingeführt wurde. Implementierer dieser Schnittstelle werden während der Startphase des Kontextes benachrichtigt und können jede programmgesteuerte Registrierung über den bereitgestellten ServletContext durchführen.

Spring implementiert den ServletContainerInitializer über die SpringServletContainerInitializer-Klasse. Pro den Servlet-Spezifikationen, muss diese Umsetzung in einer META-INF/service/javax.servlet.ServletContainerInitializer Datei der Dateibibliotheken jar deklariert werden - Frühling dies erklärt im Frühjahr-web * .jar-JAR-Datei und hat einen Eintrag org.springframework.web.SpringServletContainerInitializer

SpringServletContainerInitializer Klasse eine @HandlerTypes Annotation mit einem Wert von WebApplicationInitializer hat, bedeutet dies, dass die Servlet-Container für die Klassen scannen die WebApplicationInitializer Implementierung und rufen Sie die OnStartup Methode mit diesen Klassen der Implementierung und das ist, wo die WebApplicationInitializer in passen.

A wenig verworren, aber das Gute daran ist, dass all diese Details innerhalb des Spring-Web-Frameworks völlig abstrahiert sind und der Entwickler nur noch konfigurieren muss e eine Implementierung von WebApplicationInitializer und leben in einer web.xml freien Welt.

+0

Aber Spring verwendet keine @ WebServlet-Annotation. – Finkelson

+0

Ja, richtig, ich habe meine Antwort aktualisiert –

Verwandte Themen