SpringBoot嵌入式Servlet配置原理 SpringBoot修改服务器配置
配置文件方式方式修改,实际修改的是ServerProperties文件中的值
server.servlet.context-path=http://www.likecs.com/crud server.port=8081Java代码方式修改。通过实现WebServerFactoryCusomizer接口来获取到达ConfigurableServletWebServerFactory的通道,ConfigurableServletWebServerFactory中提供了很多的方法用来修改服务器配置。
@Component public class ServletHandler implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { @Override public void customize(ConfigurableServletWebServerFactory factory) { factory.setPort(8083); } } SpringBoot使用原生web组件在之前的Web项目中,我们会通过web.xml来注册三大组件,在springboot中我们通过提供的类注册三大组件
Servlet。通过ServletRegistrationBean来注册一个Servlet
@Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean registration = new ServletRegistrationBean(new MyServlet(),"/hello"); return registration; }Filter。通过FilterRegistrationBean来祖册Filter
@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new MyFilter()); filterRegistrationBean.setUrlPatterns(Arrays.asList("/hello")); return filterRegistrationBean ; }Listener。通过ServletListenerRegistrationBean来注册一个监听器
@Bean public ServletListenerRegistrationBean myServletListener(){ ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean(); registrationBean.setListener(new MyServletContextListener()); return registrationBean ; } Spring使用其他服务器SpringBoot提供了三个服务器工厂,Tomcat,Jetty,Undertow,默认使用了Tomcat
使用Jetty。需要排除Tomcat依赖
<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>使用Undertow服务器。同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-undertow</artifactId> <groupId>org.springframework.boot</groupId> </dependency> SpringBoot服务器自动配置原理Springboot通过WebServerInitializedEvent来实现服务器自动配置,通过这个类来加载一个WebServer
public abstract class WebServerInitializedEvent extends ApplicationEvent { protected WebServerInitializedEvent(WebServer webServer) { super(webServer); }通过WebServer来创建固定的服务器。
TomcatWebServer
JettyWebServer
NettyWebServer
UndertowWebServer
public interface WebServer { void start() throws WebServerException; void stop() throws WebServerException; int getPort(); } SpringBoot启动Tomcat服务器的过程SpringBoot启动方法
SpringApplication.run(DemoApplication.class, args)调用SpringAllication.run方法返回了ConfigurableApplicationContext对象
public ConfigurableApplicationContext run(String... args) { context = this.createApplicationContext();//创建了一个Application对象 this.refreshContext(context);//刷新ApplicationContext protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch(this.webApplicationType) { case SERVLET: contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); break; case REACTIVE: contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); break; default: contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); } } catch (ClassNotFoundException var3) { throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3); } } return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass); }创建了AnnotationConfigReactiveWebServerApplicationContext这个类最终实现了AbstractApplicationContext
private void refreshContext(ConfigurableApplicationContext context) { this.refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException var3) { } } } protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext)applicationContext).refresh(); } public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); //调用子类的刷新方法,最终调用的是创建ApplicationContext容器中所选择的容器即ServletWebServerApplicationContext类中的方法 this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } } protected void onRefresh() { super.onRefresh(); try { //创建了web容器 this.createWebServer(); } catch (Throwable var2) { throw new ApplicationContextException("Unable to start web server", var2); } } private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = this.getServletContext(); //当容器中没有服务器的时候 if (webServer == null && servletContext == null) { //创建一个web服务器, ServletWebServerFactory factory = this.getWebServerFactory(); this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); } else if (servletContext != null) { try { this.getSelfInitializer().onStartup(servletContext); } catch (ServletException var4) { throw new ApplicationContextException("Cannot initialize servlet context", var4); } } this.initPropertySources(); } protected ServletWebServerFactory getWebServerFactory() { //获取了容器中ServletWebServerFactory类型的容器 String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean."); } else if (beanNames.length > 1) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } else { //创建了web服务器 return (ServletWebServerFactory)this.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); } }