SpringBoot動態注冊Servlet


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容器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM