2015-09-13 15 views
6

Tôi tự hỏi làm thế nào để Tomcat khởi động ứng dụng của tôi trên Spring MVC?Tomcat chính xác khởi động ứng dụng mà không cần web.xml như thế nào?

Tôi có một initializer:

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("/"); 
    } 
} 

tôi biết lý do tại sao chúng ta cần web.xml và làm thế nào Tomcat sử dụng nó để bootstrap ứng dụng. Nhưng tôi không hiểu làm thế nào để Tomcat biết servlet nào nên sử dụng để khởi động ứng dụng nếu không có tệp xml, nhưng chỉ AppAppInitializer?

Dependencies

<!-- 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> 

... 

tôi thấy lớp này trong mùa xuân lõi SpringServletContainerInitializer. Có đúng là Tomcat sử dụng nó để khởi động ứng dụng của tôi không?

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

Trả lời

13

Servlet 3.0 đã thêm cơ chế pluggability. Cách hoạt động là khi ứng dụng của bạn được tải, ứng dụng sẽ quét đường dẫn lớp cho META-INF/services và tìm tệp có tên javax.servlet.ServletContainerInitializer. Trong đó trình cài đặt phải có tên của việc triển khai thực hiện, nơi mà thùng chứa servlet có thể tải nó. Bạn có thể xem tệp này trong lọ spring-web.Nó liệt kê org.springframework.web.SpringServletContainerInitializer khi triển khai bộ khởi tạo.

Trình khởi tạo Spring hoạt động như thế nào, là nó được chuyển tất cả các triển khai (trên đường dẫn lớp) của WebApplicationInializer bởi thùng chứa servlet. Vì vậy, làm thế nào để thùng chứa servlet biết để vượt qua những triển khai này? Nếu bạn nhìn vào source code for the inializer, bạn sẽ thấy

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

Đây là @HandlesType chú thích. Tất cả các lớp thậm chí chú thích [] liệt kê trong @HandlesTypes sẽ được chọn bởi các container servlet và truyền cho SevletContainerInitializer qua đối số phương pháp đơn callback

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

Đối số Set chứa tất cả các triển khai được chọn bởi thùng chứa servlet trong khi quét. Bạn có thể xem qua mã nguồn để xem Spring làm gì với những triển khai đó. Về cơ bản, nó chỉ gọi onStartup của tất cả các thiết bị inializers, đi qua trong ServletContext.


[] - Đó là nghe một chút không rõ ràng (và giải thích nó ở trên sẽ được đi một chút tắt trên tiếp tuyến) vì vậy tôi sẽ chỉ gửi nó như một thêm ở đây.

Hãy tưởng tượng @HandlesType thay vì là

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

Điều này có nghĩa rằng servlet container cũng sẽ quét cho các lớp chú thích với @Controller, và cũng có thể vượt qua những vào onStartup của initializer mùa xuân.

+1

Cảm ơn. Bây giờ tôi biết cách nó hoạt động. – Finkelson

1

Nó được kết nối với một thực tế, rằng API Servlet 3.0 đang làm việc mà không web.xml. Vì vậy, nó không phải là một tính năng mùa xuân.

Thông tin thêm ở đây: https://blogs.oracle.com/swchan/entry/servlet_3_0_annotations

JSR 315: JavaTM Servlet 3.0 Đặc điểm kỹ thuật: https://jcp.org/en/jsr/detail?id=315

UPD:

Xuân WebApplicationInitializer cung cấp một cách programatic để cấu hình DispatcherServlet xuân và ContextLoaderListener trong Servlet 3.0+ thùng chứa servlet tuân thủ, thay vì thêm cấu hình này thông qua tệp web.xml.

Câu trả lời là giao diện ServletContainerInitializer được giới thiệu với đặc tả Servlet 3.0, những người triển khai giao diện này được thông báo trong giai đoạn khởi động ngữ cảnh và có thể thực hiện bất kỳ đăng ký chương trình nào thông qua ServletContext đã cung cấp.

Spring triển khai ServletContainerInitializer thông qua lớp SpringServletContainerInitializer. Theo thông số kỹ thuật Servlet, việc triển khai này phải được khai báo trong tệp META-INF/services/javax.servlet.ServletContainerInitializer của tệp jar thư viện - Spring tuyên bố tệp này trong tệp jar jar jar-web * và có mục nhập org.springframework.web.SpringServletContainerInitializer

SpringServletContainerInitializer lớp có chú thích với một giá trị của WebApplicationInitializer @HandlerTypes, điều này có nghĩa rằng Servlet container sẽ quét cho các lớp triển khai thực hiện WebApplicationInitializer và gọi phương thức onStartUp với các lớp này và đó là nơi mà các WebApplicationInitializer phù hợp.

một ít phức tạp, nhưng điều tốt là tất cả những chi tiết này hoàn toàn trừu tượng trong khung công tác mùa xuân và nhà phát triển chỉ phải cấu hình e thực hiện WebApplicationInitializer và sống trong thế giới web.xml miễn phí.

+0

Nhưng Spring không sử dụng chú thích @WebServlet. – Finkelson

+0

vâng, đúng, tôi đã cập nhật câu trả lời của mình –

Các vấn đề liên quan