簡介
在web容器啟動時為提供給第三方組件機會做一些初始化的工作,例如注冊servlet或者filtes等,servlet規范中通過ServletContainerInitializer實現此功能。
每個框架要使用ServletContainerInitializer就必須在對應的jar包的META-INF/services 目錄創建一個名為javax.servlet.ServletContainerInitializer的文件,文件內容指定具體的ServletContainerInitializer實現類。
實現步驟
1、Servlet容器啟動會掃描,當前應用里面每一個jar包的
ServletContainerInitializer的實現
2、提供ServletContainerInitializer的實現類;
必須綁定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的內容就是ServletContainerInitializer實現類的全類名;
3、代碼:
MyServletContainerInitializer.java
//容器啟動的時候會將@HandlesTypes指定的這個類型下面的子類(實現類,子接口等)傳遞過來; //傳入感興趣的類型; @HandlesTypes(value={HelloService.class}) public class MyServletContainerInitializer implements ServletContainerInitializer { /** * 應用啟動的時候,會運行onStartup方法; * * Set<Class<?>> arg0:感興趣的類型的所有子類型; * ServletContext arg1:代表當前Web應用的ServletContext;一個Web應用一個ServletContext; * * 1)、使用ServletContext注冊Web組件(Servlet、Filter、Listener) * 2)、使用編碼的方式,在項目啟動的時候給ServletContext里面添加組件; * 必須在項目啟動的時候來添加; * 1)、ServletContainerInitializer得到的ServletContext; * 2)、ServletContextListener得到的ServletContext; */ @Override public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException { // TODO Auto-generated method stub System.out.println("感興趣的類型:"); for (Class<?> claz : arg0) { System.out.println(claz); } //注冊組件 ServletRegistration ServletRegistration.Dynamic servlet = sc.addServlet("userServlet", new UserServlet()); //配置servlet的映射信息 servlet.addMapping("/user"); //注冊Listener sc.addListener(UserListener.class); //注冊Filter FilterRegistration FilterRegistration.Dynamic filter = sc.addFilter("userFilter", UserFilter.class); //配置Filter的映射信息 filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); } }
總結
1,HandlesTypes作用是將注解指定的class對象作為參數傳遞到onstartup(servletcontainerInitializer)中,技術就是bcel,這個是Jakarta的一部分,類似asm。
2,容器在啟動應用的時候,會掃描當前應用每一個jar包里面META-INF/services/javax.servlet.ServletContainerInitializer指定的實現類,啟動並運行這個實現類的方法;傳入感興趣的類型。
鏈接: https://www.jianshu.com/p/2b09d81ccab8