最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

 更新時(shí)間:2023年12月06日 10:31:48   作者:程序猿進(jìn)階  
傳統(tǒng)的Spring MVC工程部署時(shí)需要將WAR文件放置在servlet容器的文檔目錄內(nèi),而Spring Boot工程使用嵌入式servlet容器省去了這一步驟,本文就來(lái)設(shè)置一下相關(guān)配置,感興趣的可以了解一下

一、如何定制和修改Servlet容器的相關(guān)配置

前言: SpringBootWeb環(huán)境下,默認(rèn)使用的是Tomact作為嵌入式的Servlet容器;

在這里插入圖片描述

【1】修改和server相關(guān)的配置(ServerProperties實(shí)現(xiàn)了EmbeddedServletContainerCustomizer)例如:修改端口號(hào)

#通用的Servlet容器設(shè)置:修改端口號(hào)
server:
  port: 8081
  tomcat:  #設(shè)置Tomact的相關(guān)屬性,例如編碼格式
    uri-encoding: utf-8

? 我們也可以進(jìn)入port所屬的對(duì)象中,發(fā)現(xiàn)其他可修改的參數(shù)等等,如下:

@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
    private Integer port;
    private InetAddress address;
    private String contextPath;
    private String displayName = "application";
    ......

【2】編寫(xiě)一個(gè)EmbeddedServletContainerCustomizer:嵌入式的 Servlet容器的定制器,來(lái)修改 Servlet容器的配置。其實(shí)1中的 ServerProperties也是實(shí)現(xiàn)了 EmbeddedServletContainerCustomizer。xxxCustomizer 幫組我們進(jìn)行定制配置。

@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                container.setPort(8082);
            }
        };
    }

二、注冊(cè)Servlet三大組件【Servlet、Filter、Listener】

由于SpringBoot默認(rèn)是以 jar包的方式啟動(dòng)嵌入的Servlet容器來(lái)啟動(dòng)SpringBootweb應(yīng)用,沒(méi)有web.xml文件。注冊(cè)三大組件的方式如下:

【1】通過(guò) ServletRegistrationBean注冊(cè)自定義的Servlet

//首先創(chuàng)建一個(gè)Servlet
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello MyServlet");
        super.doPost(req, resp);
    }
}

//將創(chuàng)建的Servlet通過(guò)配置類注入到容器中,兩個(gè)是不同的類。
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public ServletRegistrationBean myServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(), "/myServlet");
        return registrationBean;
    }

【2】通過(guò) FilterRegistrationBean 注冊(cè)攔截器 Filter。

//自定義一個(gè)filter實(shí)現(xiàn)servlet.Filter接口
public class myFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.printf("myFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

//通過(guò)配置類注入自定義的Filter
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new myFilter());
        registrationBean.setUrlPatterns(Arrays.asList("/hello","/myFilter"));
        return registrationBean;
    }
【3】通過(guò)`ServletListenerRegistrationBean`注冊(cè)自定義的`Listener`。
```java
//創(chuàng)建自定義的Listener監(jiān)聽(tīng)
public class myListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.printf("服務(wù)啟動(dòng)");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.printf("服務(wù)銷毀");
    }
}

//通過(guò)配置類注入自定義的listener
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {

    public ServletListenerRegistrationBean myListener(){
        ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(new MyListener());
        return servletListenerRegistrationBean;
    }

三、使用其他 Servlet容器:Jetty(長(zhǎng)連接引用)、Undertow(不支持JSP)

【1】我們?cè)诙ㄖ魄度胧降?code>Servlet容器時(shí),會(huì)傳入ConfigurableEmbeddedServletContainer類,我們通過(guò)Ctrl+T查看此可配置嵌入式類容器中可以配置Tomcat、JettyUndertow。

//ConfigurableEmbeddedServletContainer 
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.setPort(8082);
        }
    };
}

【2】默認(rèn)使用Tomcat,因?yàn)?code>starter-web引入的是Tomcatstarter。我們排除Tomcat的依賴,引入Jetty的依賴即可。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<groupId>org.springframework.boot</groupId>
		</exclusion>
	</exclusions>
</dependency>

<dependency>
	<artifactId>spring-boot-starter-Jetty</artifactId>
	<groupId>org.springframework.boot</groupId>
</dependency>

四、嵌入式 Servlet容器自動(dòng)配置原理

【1】EmbeddedServletContainerAutoConfiguration類主要用來(lái)自動(dòng)配置嵌入式的Servlet容器。

@AutoConfigureOrder(-2147483648)
@Configuration
@ConditionalOnWebApplication
 //導(dǎo)入BeanPostProcessorsRegistrar:后置處理器:在bean初始化前后,執(zhí)行(剛創(chuàng)建完對(duì)象,還沒(méi)屬性賦值)初始化工作.
 //給容器中導(dǎo)入一些組件,導(dǎo)入了embeddedServletContainerCustomizerBeanPostProcessor
@Import({EmbeddedServletContainerAutoConfiguration.BeanPostProcessorsRegistrar.class})
public class EmbeddedServletContainerAutoConfiguration {
    @Configuration
    @ConditionalOnClass({Servlet.class, Tomcat.class})//判斷當(dāng)前Servlet中是否引入的Tomcat依賴
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )//判斷當(dāng)前容器中,沒(méi)有用戶自定義的EmbeddedServletContainerFactory嵌入式的Servlet容器工廠,
    //作用:創(chuàng)建嵌入式的servlet容器。
    public static class EmbeddedTomcat {
        public EmbeddedTomcat() {
        }

        @Bean
        public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
            return new TomcatEmbeddedServletContainerFactory();
        }
    }

    @Configuration
    @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class})
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )
    public static class EmbeddedUndertow {
        public EmbeddedUndertow() {
        }

        @Bean
        public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
            return new UndertowEmbeddedServletContainerFactory();
        }
    }

    @Configuration
    @ConditionalOnClass({Servlet.class, Server.class, Loader.class, WebAppContext.class})
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )
    public static class EmbeddedJetty {
        public EmbeddedJetty() {
        }

        @Bean
        public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
            return new JettyEmbeddedServletContainerFactory();
        }
    }
}

【2】嵌入式的容器工廠:EmbeddedServletContainerFactory,用來(lái)創(chuàng)建嵌入式的Servlet容器。

public interface EmbeddedServletContainerFactory {
     //獲取嵌入式的Servlet容器
     EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... var1); 
}

? SpringBoot 再帶了三種嵌入式的容器工廠,如下:

【3】EmbeddedServletContainer:嵌入式的容器,SpringBoot 為我們提供了三種不同的嵌入式容器,與工廠相互對(duì)應(yīng),如下:

【4】我們進(jìn)入工廠類 TomcatEmbeddedServletContainerFactory發(fā)現(xiàn),其實(shí)也是創(chuàng)建一個(gè) Tomcat并配置其基本屬性。

public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
	//創(chuàng)建Tomcat
	Tomcat tomcat = new Tomcat();

	//配置Tomcat的基本環(huán)境
	File baseDir = this.baseDirectory != null?this.baseDirectory:this.createTempDir("tomcat");
	tomcat.setBaseDir(baseDir.getAbsolutePath());
	Connector connector = new Connector(this.protocol);
	tomcat.getService().addConnector(connector);
	this.customizeConnector(connector);
	tomcat.setConnector(connector);
	tomcat.getHost().setAutoDeploy(false);
	this.configureEngine(tomcat.getEngine());
	Iterator var5 = this.additionalTomcatConnectors.iterator();

	while(var5.hasNext()) {
		Connector additionalConnector = (Connector)var5.next();
		tomcat.getService().addConnector(additionalConnector);
	}

	this.prepareContext(tomcat.getHost(), initializers);
	//將配置好的Tomcat傳入,并啟動(dòng)Tomcat,Tomcat.start()
	return this.getTomcatEmbeddedServletContainer(tomcat);
}

【5】用戶自定義的Servlet容器配置類和SpringBoot默認(rèn)的ServerProperties配置類,都實(shí)現(xiàn)了EmbeddedServletContainerCustomizer接口。到底是怎么實(shí)現(xiàn)的哪?其實(shí)是SpringBoot自動(dòng)配置類中引入了后置處理器,如下:

//與用戶自定義的Servlet容器實(shí)現(xiàn)的接口名很類似,有一定的命名規(guī)則。
embeddedServletContainerCustomizerBeanPostProcessor

? 進(jìn)入后置處理器類中,重點(diǎn)看如下代碼:

//初始化之前執(zhí)行
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	//如果當(dāng)前初始化的是當(dāng)前ConfigurableEmbeddedServletContainer類型的組件
	if(bean instanceof ConfigurableEmbeddedServletContainer) {
		this.postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer)bean);
	}

	return bean;
}

//上面的postProcessBeforeInitialization方法:
private void postProcessBeforeInitialization(ConfigurableEmbeddedServletContainer bean) {
	Iterator var2 = this.getCustomizers().iterator();

	while(var2.hasNext()) {
		//獲取所有的定制器,調(diào)用每一個(gè)定制器的customize方法來(lái)給servlet屬性賦值。
		EmbeddedServletContainerCustomizer customizer = (EmbeddedServletContainerCustomizer)var2.next();
		customizer.customize(bean);
	}

private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
	if(this.customizers == null) {
		//this.beanFactory.xx表示從容器中獲取XXCustomizer自定義類型的組件
		this.customizers = new ArrayList(this.beanFactory.getBeansOfType(EmbeddedServletContainerCustomizer.class, false, false).values());
		Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
		this.customizers = Collections.unmodifiableList(this.customizers);
	}

	return this.customizers;
}

整理下步驟:
【1】SpringBoot根據(jù)pom.xml中導(dǎo)入的依賴,給容器中添加其對(duì)應(yīng)的嵌入式的服務(wù)容器工廠類,例如默認(rèn)的Tomcat工廠:EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
【2】給容器中某個(gè)組件要?jiǎng)?chuàng)建對(duì)象就會(huì)觸發(fā)后置處理器EmbeddedServletContainerCustomizerBeanPostProcessor,只要是嵌入式的Servlet容器工廠,后置處理器就會(huì)工作(默認(rèn)的ServerProperties也是實(shí)現(xiàn)了此類接口的,所以肯定存在相關(guān)配置類)
【3】后置處理器從容器中獲取所有的EmbeddedServletContainerCustomizer,調(diào)用定制器的定制方法。

五、嵌入式Servlet容器啟動(dòng)原理

根據(jù)上述的流程,我們要研究Servlet容器的啟動(dòng)原理。其實(shí)就是研究什么時(shí)候創(chuàng)建嵌入式的容器工廠和何時(shí)獲取嵌入式的容器并啟動(dòng)Tomcat。獲取嵌入式的Servlet容器工廠的過(guò)程(在new TomcatEmbeddedServletContainerFactory()時(shí)打一個(gè)斷電,查看過(guò)程):
【1】SpringBoot 應(yīng)用啟動(dòng)運(yùn)行 run() 方法。
【2】this.refreshContext(context) 方法:用來(lái)初始化 IOC容器,既創(chuàng)建 IOC容器對(duì)象并初始化IOC容器中的每一個(gè)組件。

protected ConfigurableApplicationContext createApplicationContext() {
	Class<?> contextClass = this.applicationContextClass;
	if(contextClass == null) {
		try {
			//判斷是不是web環(huán)境,是Web環(huán)境引入AnnotationConfigEmbeddedWebApplicationContext,否則引入AnnotationConfigApplicationContext
			contextClass = Class.forName(this.webEnvironment
			?"org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"
			:"org.springframework.context.annotation.AnnotationConfigApplicationContext");
		} catch (ClassNotFoundException var3) {
			throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
		}
	}

	return (ConfigurableApplicationContext)BeanUtils.instantiate(contextClass);
}

【3】this.refresh(context):刷新剛才創(chuàng)建好的IOC容器。
【4】this.onRefresh()webIoC容器重寫(xiě)了onRefresh()方法。

protected void onRefresh() {
	super.onRefresh();

	try {
		//重點(diǎn)是創(chuàng)建了嵌入式的Servlet容器
		this.createEmbeddedServletContainer();
	} catch (Throwable var2) {
		throw new ApplicationContextException("Unable to start embedded container", var2);
	}
}

【5】this.createEmbeddedServletContainer()webIOC容器會(huì)創(chuàng)建嵌入式的Servlet容器。

private void createEmbeddedServletContainer() {
	EmbeddedServletContainer localContainer = this.embeddedServletContainer;
	ServletContext localServletContext = this.getServletContext();
	if(localContainer == null && localServletContext == null) {
		// 1、獲取嵌入式的Servlet嵌入式的工廠
		EmbeddedServletContainerFactory containerFactory = this.getEmbeddedServletContainerFactory();
		this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(
				new ServletContextInitializer[]{this.getSelfInitializer()});
	} 
}

【6】獲取嵌入式工廠后,便可從容器中獲取EmbeddedServletContainerFactory的組件tomcatEmbeddedServletContainerFactory來(lái)創(chuàng)建Tomcat對(duì)象,后置處理器就會(huì)觸發(fā)獲取所有的定制器來(lái)確定Servlet容器的相關(guān)配置。
【7】通過(guò)嵌入式工廠獲取嵌入式容器,如下:

this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(
                new ServletContextInitializer[]{this.getSelfInitializer()});

● 嵌入式的Servlet容器創(chuàng)建并啟動(dòng)對(duì)象:

public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
    //創(chuàng)建對(duì)象
    Tomcat tomcat = new Tomcat();

    //啟動(dòng)對(duì)象
    this.tomcat.start();

● 先啟動(dòng)嵌入式的Servlet容器,再將IOC容器中剩下沒(méi)有創(chuàng)建的對(duì)象進(jìn)行初始化,如下:

    this.onRefresh();
    //啟動(dòng)完嵌入式容器后,后續(xù)還有其他對(duì)象的初始化工作
    this.registerListeners();
    this.finishBeanFactoryInitialization(beanFactory);
    this.finishRefresh();
} catch (BeansException var9) {

六、使用外置的Servlet容器

嵌入式Servlet容器的缺點(diǎn): 默認(rèn)不支持JSP、優(yōu)化和定制比較復(fù)雜。外置Servlet容器:安裝外部的Tomcat,步驟如下:

1)、必須創(chuàng)建一個(gè)war項(xiàng)目,需要手動(dòng)創(chuàng)建目錄(利用Idea快速創(chuàng)建)如下:

?

2)、將嵌入式的Tomcat指定為provide(Idea創(chuàng)建完后,會(huì)自動(dòng)幫我們完成,但我們需要了解)

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
	<scope>provided</scope>
</dependency>

3)、需要編寫(xiě)一個(gè)SpringBootServletInitializer的子類,并調(diào)用configure方法:

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(SpringBootWebApplication.class);
	}
}

4)、配置本地的Tomcat,并啟動(dòng)Tomcat即可。(此項(xiàng)目運(yùn)行run()方法是不能啟動(dòng)項(xiàng)目的):需要設(shè)置名稱和本地Tomcat的路徑即可使用外部Servlet。

七、外置服務(wù)器的使用原理

? jar包:執(zhí)行SpringBoot主類的main方法,啟動(dòng)并初始化IOC容器且創(chuàng)建嵌入式的Servlet容器。
? war包:?jiǎn)?dòng)服務(wù)器后調(diào)用SpringBootServletInitializer中的configure()方法,加載我們的SpringBoot應(yīng)用并啟動(dòng)。

Servlet3.0規(guī)則:
 1)、服務(wù)器啟動(dòng)后,會(huì)創(chuàng)建當(dāng)前web應(yīng)用中包含的每個(gè)jar內(nèi)的ServletContainerInitializer實(shí)例。
 2)、ServletContainerInitializer的實(shí)現(xiàn)放在jar包的META-INF/services文件夾下(javax.servlet.ServletContainerInitializer:內(nèi)容就是ServletContainerInitializer的全類名)
 3)、可以使用@handlesTypes注解,在應(yīng)用啟動(dòng)時(shí)加載我們需要的類。

流程: 1)、啟動(dòng)Tomcat后,獲取servlet.ServletContainerInitializer文件如下:其中的內(nèi)容同下:

在這里插入圖片描述

#文件中的內(nèi)容
org.springframework.web.SpringServletContainerInitializer

 2)、進(jìn)入SpringServletContainerInitializer發(fā)現(xiàn)此類將@HandlesTypes({WebApplicationInitializer.class})標(biāo)注的所有這個(gè)類型的類都傳入到onStartup方法中的Set<Class<?>>,并為這些類創(chuàng)建實(shí)例。

@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    //onStartup方法,用來(lái)實(shí)例化感興趣的對(duì)象
    public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
        if(webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                if(!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                            //實(shí)例化
                       initializers.add((WebApplicationInitializer)waiClass.newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

 3)、每一個(gè)WebApplicationInitializer都調(diào)用自己的onStartup()方法。

while(var4.hasNext()) {
	  WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
	  //onStartup()方法
	  initializer.onStartup(servletContext);
 }

 4)、WebApplicationInitializer只是一個(gè)接口,其實(shí)現(xiàn)類主要有以下三個(gè):SpringBootServletInitalizer正是SpringBoot給我們創(chuàng)建好的啟動(dòng)類,會(huì)被創(chuàng)建對(duì)象,并啟動(dòng)自身的onStartup()方法。

 5)、執(zhí)行onStartup()方法時(shí),會(huì)調(diào)用createRootApplicationContext()方法來(lái)創(chuàng)建容器

public void onStartup(ServletContext servletContext) throws ServletException {
        this.logger = LogFactory.getLog(this.getClass());
        //創(chuàng)建容器
        WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext);
        if(rootAppContext != null) {
            servletContext.addListener(new ContextLoaderListener(rootAppContext) {
                public void contextInitialized(ServletContextEvent event) {
                }
            });

    //容器的具體調(diào)用實(shí)現(xiàn)
    protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
        //創(chuàng)建Spring應(yīng)用的構(gòu)建器
        SpringApplicationBuilder builder = this.createSpringApplicationBuilder();
        //設(shè)置主類
        builder.main(this.getClass());
        //創(chuàng)建一些環(huán)境
        ApplicationContext parent = this.getExistingRootWebApplicationContext(servletContext);
        if(parent != null) {
            this.logger.info("Root context already created (using as parent).");
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, (Object)null);
            builder.initializers(new ApplicationContextInitializer[]{new ParentContextApplicationContextInitializer(parent)});
        }

        builder.initializers(new ApplicationContextInitializer[]{new ServletContextApplicationContextInitializer(servletContext)});
        builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);

        //重要:子類中重寫(xiě)了此方法,子類出入了應(yīng)用的主程序類
        builder = this.configure(builder);
        builder.listeners(new ApplicationListener[]{new SpringBootServletInitializer.WebEnvironmentPropertySourceInitializer(servletContext, null)});
        //使用build()創(chuàng)建一個(gè)Spring應(yīng)用
        SpringApplication application = builder.build();
        if(application.getAllSources().isEmpty() && AnnotationUtils.findAnnotation(this.getClass(), Configuration.class) != null) {
            application.addPrimarySources(Collections.singleton(this.getClass()));
        }

        Assert.state(!application.getAllSources().isEmpty(), "No SpringApplication sources have been defined. Either override the configure method or add an @Configuration annotation");
        if(this.registerErrorPageFilter) {
            application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
        }
        //啟動(dòng)應(yīng)用
        return this.run(application);
    }

 6)、執(zhí)行應(yīng)用的run()方法,來(lái)啟動(dòng)Spring應(yīng)用并創(chuàng)建IOC容器。

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
	this.configureHeadlessProperty();
	SpringApplicationRunListeners listeners = this.getRunListeners(args);
	listeners.starting();

	Collection exceptionReporters;
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
		this.configureIgnoreBeanInfo(environment);
		Banner printedBanner = this.printBanner(environment);
		context = this.createApplicationContext();
		exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context});
		this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

		//刷新IOC容器
		this.refreshContext(context);
		this.afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if(this.logStartupInfo) {
			(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
		}

		listeners.started(context);
		this.callRunners(context, applicationArguments);
	} catch (Throwable var10) {
		this.handleRunFailure(context, var10, exceptionReporters, listeners);
		throw new IllegalStateException(var10);
	}

	try {
		listeners.running(context);
		return context;
	} catch (Throwable var9) {
		this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
		throw new IllegalStateException(var9);
	}
}

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器的文章就介紹到這了,更多相關(guān)SpringBoot 嵌入式 Servlet容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • springboot 動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方法(Mybatis+Druid)

    springboot 動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方法(Mybatis+Druid)

    這篇文章主要介紹了springboot 動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方法(Mybatis+Druid),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Java項(xiàng)目打包發(fā)布到maven私倉(cāng)常見(jiàn)的幾種方式

    Java項(xiàng)目打包發(fā)布到maven私倉(cāng)常見(jiàn)的幾種方式

    這篇文章主要介紹了項(xiàng)目打包發(fā)布到maven私倉(cāng)常見(jiàn)的幾種方式,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • 關(guān)于@Data和@Builder注解解析

    關(guān)于@Data和@Builder注解解析

    在使用Lombok庫(kù)時(shí),@Data和@Builder注解混用可能會(huì)導(dǎo)致編譯失敗,解決方法包括添加@NoArgsConstructor和@AllArgsConstructor注解,或者重寫(xiě)無(wú)參構(gòu)造器并注解@Tolerate,這是因?yàn)锧Data自動(dòng)生成的構(gòu)造器與@Builder的構(gòu)造模式存在沖突
    2024-10-10
  • 在SpringBoot中使用ResponseBodyAdvice自定義響應(yīng)的代碼實(shí)現(xiàn)

    在SpringBoot中使用ResponseBodyAdvice自定義響應(yīng)的代碼實(shí)現(xiàn)

    ResponseBodyAdvice是Spring Framework中的一個(gè)接口,允許您在將響應(yīng)寫(xiě)入客戶端之前自定義響應(yīng),它通常與@ControllerAdvice注釋結(jié)合使用,以跨多個(gè)控制器將全局更改應(yīng)用于響應(yīng)主體,本文介紹了如何使用ResponseBodyAdvice的基本概述,需要的朋友可以參考下
    2024-12-12
  • SpringBoot中實(shí)現(xiàn)訂單30分鐘自動(dòng)取消的三種方案分享

    SpringBoot中實(shí)現(xiàn)訂單30分鐘自動(dòng)取消的三種方案分享

    在電商和其他涉及到在線支付的應(yīng)用中,通常需要實(shí)現(xiàn)一個(gè)功能:如果用戶在生成訂單后的一定時(shí)間內(nèi)未完成支付,系統(tǒng)將自動(dòng)取消該訂單,本文將詳細(xì)介紹基于Spring Boot框架實(shí)現(xiàn)訂單30分鐘內(nèi)未支付自動(dòng)取消的幾種方案,并提供實(shí)例代碼,需要的朋友可以參考下
    2023-10-10
  • SpringBoot + Druid + Dynamic Datasource 多數(shù)據(jù)源配置方案

    SpringBoot + Druid + Dynamic Dataso

    本文通過(guò)實(shí)例代碼給大家介紹SpringBoot整合Druid與多數(shù)據(jù)源配置,涵蓋自動(dòng)裝配流程、數(shù)據(jù)源動(dòng)態(tài)切換方案及監(jiān)控功能實(shí)現(xiàn),感興趣的朋友一起看看吧
    2025-08-08
  • Java處理JSON編程實(shí)用技巧和性能優(yōu)化

    Java處理JSON編程實(shí)用技巧和性能優(yōu)化

    JSON解析是Java Web開(kāi)發(fā)的核心技能,用于服務(wù)端和客戶端間數(shù)據(jù)交換,下面這篇文章主要介紹了Java處理JSON編程實(shí)用技巧和性能優(yōu)化的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-11-11
  • Java發(fā)送報(bào)文與接收?qǐng)?bào)文的實(shí)例代碼

    Java發(fā)送報(bào)文與接收?qǐng)?bào)文的實(shí)例代碼

    這篇文章主要介紹了Java發(fā)送報(bào)文與接收?qǐng)?bào)文,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot入門實(shí)現(xiàn)第一個(gè)SpringBoot項(xiàng)目

    SpringBoot入門實(shí)現(xiàn)第一個(gè)SpringBoot項(xiàng)目

    今天我們一起來(lái)完成一個(gè)簡(jiǎn)單的SpringBoot(Hello World)。就把他作為你的第一個(gè)SpringBoot項(xiàng)目。具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-09-09
  • mybatis-plus配置日志兩種實(shí)現(xiàn)方式

    mybatis-plus配置日志兩種實(shí)現(xiàn)方式

    這篇文章主要給大家介紹了關(guān)于mybatis-plus配置日志兩種實(shí)現(xiàn)方式的相關(guān)資料,Mybatis-plus集成了日志框架,可以將程序運(yùn)行時(shí)產(chǎn)生的日志進(jìn)行記錄,方便開(kāi)發(fā)人員進(jìn)行問(wèn)題排查,需要的朋友可以參考下
    2023-09-09

最新評(píng)論

孟津县| 长葛市| 图木舒克市| 浮山县| 乌鲁木齐市| 岑溪市| 中山市| 昌平区| 东兰县| 江安县| 寿光市| 涿州市| 张家界市| 卢氏县| 鄯善县| 朝阳县| 蒲江县| 遂昌县| 射洪县| 抚州市| 兰坪| 云霄县| 马尔康县| 阿巴嘎旗| 新邵县| 陇川县| 共和县| 固阳县| 绥化市| 寻乌县| 北京市| 磴口县| 铁岭县| 翁牛特旗| 耒阳市| 阜城县| 安达市| 新干县| 惠安县| 抚州市| 新巴尔虎右旗|