1、SpringBoot配置自定義監聽器
實質上是在servlet3.0+的容器中,注冊一個Servlet。
功能:監聽對應的請求路徑url-api
@Slf4j @Configuration public class SpringBootAutoConfigure { // 配置監聽器 @Bean("xxxListener") public ServletRegistrationBean<XxxServlet> createtListener() { log.info("監聽請求的路徑 /url-api..."); ServletRegistrationBean<XxxServlet> bean = new ServletRegistrationBean<>( new XxxServlet()); //添加參數至LinkedHashMap bean.addInitParameter("aaaController", "aaaController"); bean.addInitParameter("bbbController", "bbbController"); bean.addUrlMappings("/url-api"); return bean; } } // 設置參數的方法 public void setInitParameters(Map<String, String> initParameters) { Assert.notNull(initParameters, "InitParameters must not be null"); this.initParameters = new LinkedHashMap<>(initParameters); }
2、如何注冊Servlet
首先看看類和接口之間的依賴模型:
增加Servlet, ServletRegistrationBean使用泛型限定這個類是Servlet,通過構造函數參數為Servlet的對象,
注冊在Servlet一個servlet3.0+的容器中。
public ServletRegistrationBean(T servlet, String... urlMappings) { this(servlet, true, urlMappings); }
2.1 ServletRegistrationBean
Servlet的設置和獲取,MapperURL的設置添加等等
public class ServletRegistrationBean<T extends Servlet> extends DynamicRegistrationBean<ServletRegistration.Dynamic> { private static final String[] DEFAULT_MAPPINGS = { "/*" }; private T servlet; private Set<String> urlMappings = new LinkedHashSet<>(); private boolean alwaysMapUrl = true; private int loadOnStartup = -1; private MultipartConfigElement multipartConfig;
2.2 設置參數
public abstract class DynamicRegistrationBean<D extends Registration.Dynamic> extends RegistrationBean { private static final Log logger = LogFactory.getLog(RegistrationBean.class); private String name; private boolean asyncSupported = true; private Map<String, String> initParameters = new LinkedHashMap<>();
2.3 RegistrationBean
可以設置Servlet的啟動順序,實現了ServletContextInitializer的類將會被SpringServletContainerInitializer監測到
public abstract class RegistrationBean implements ServletContextInitializer, Ordered { private static final Log logger = LogFactory.getLog(RegistrationBean.class); private int order = Ordered.LOWEST_PRECEDENCE; private boolean enabled = true;
2.4 接口ServletContextInitializer和Ordered
@FunctionalInterface public interface ServletContextInitializer { public interface Ordered { /** * Useful constant for the highest precedence value. * @see java.lang.Integer#MIN_VALUE */ int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; /** * Useful constant for the lowest precedence value. * @see java.lang.Integer#MAX_VALUE */ int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
3、常見的初始化接口
3.1 ServletContainerInitializer
org.springframework.web.SpringServletContainerInitializer is an implementation of javax.servlet.ServletContainerInitializer.
與傳統基於web.xml的配置方式不同,Servlet3.0設計了ServletContainerInitializer,ServletContainerInitializer
支持通過Spring的WebApplicationInitializer SPI編寫基於代碼的Servlet容器配置。
3.2 WebApplicationInitializer接口幾種配置ServletContext的方式
1 傳統的web.xml,代碼示例
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
2 實現這個接口WebApplicationInitializer ,代碼示例。主要復寫onStartup方法。
public class MyWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { XmlWebApplicationContext appContext = new XmlWebApplicationContext(); appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }
3 基於代碼方式的全配置,代碼示例。
public class MyWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { // Create the 'root' Spring application context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(AppConfig.class); // Manage the lifecycle of the root application context container.addListener(new ContextLoaderListener(rootContext)); // Create the dispatcher servlet's Spring application context AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(DispatcherConfig.class); // Register and map the dispatcher servlet ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }
3.3 org.springframework.boot.web.support.SpringBootServletInitializer (class)
這是一個通過傳統的WAR包部署方式運行SpringApplication的WebApplicationInitializer實現。它可以將應用容器中的Servlet、
Filter和ServletContextInitializer相關的bean綁定到服務器(ServletContainer)。
3.4 org.springframework.boot.web.servlet.ServletContextInitializer (interface)
不同於WebApplicationInitializer,該接口的實現類不會被SpringServletContainerInitializer識別因此不會被Servlet容器自動執行。
ServletContextInitializers主要被Spring管理而不是Servlet容器。