通用的servlet容器配置 server.xx= 通用的Tomcat配置 server.tomcat.xx=
2.编写一个嵌入式Servlet容器定制器来修改Servlet容器的配置
在SpringBoot中会有xxxCustomizer来进行扩展配置,注意学习!!前端
@Configuration public class MyServerConfig { // 注册Servlet组件 @Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean servletRegistrationBean=new ServletRegistrationBean(new MyServlet(),"/my"); return servletRegistrationBean; } }
2.FilterRegistrationBeanjava
@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean(); filterRegistrationBean.setFilter(new MyFilter()); filterRegistrationBean.setUrlPatterns(Arrays.asList("/my")); return filterRegistrationBean; }
3.ServletListenerRegistrationBeanweb
@Bean public ServletListenerRegistrationBean myListener(){ ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener()); return registrationBean; }
SpringBoot自动配置SpringMVC时,自动注册SpringMVC的前端控制器:DispatcherServlet.spring
@Configuration @Conditional({DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition.class}) @ConditionalOnClass({ServletRegistration.class}) @EnableConfigurationProperties({WebMvcProperties.class}) @Import({DispatcherServletAutoConfiguration.DispatcherServletConfiguration.class}) protected static class DispatcherServletRegistrationConfiguration { private final WebMvcProperties webMvcProperties; private final MultipartConfigElement multipartConfig; public DispatcherServletRegistrationConfiguration(WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfigProvider) { this.webMvcProperties = webMvcProperties; this.multipartConfig = (MultipartConfigElement)multipartConfigProvider.getIfAvailable(); } @Bean( name = {"dispatcherServletRegistration"} ) @ConditionalOnBean( value = {DispatcherServlet.class}, name = {"dispatcherServlet"} ) public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, this.webMvcProperties.getServlet().getPath()); //能够经过修改servletpath来修改SpringMVC前端控制器默认拦截的请求路径 registration.setName("dispatcherServlet"); registration.setLoadOnStartup(this.webMvcProperties.getServlet().getLoadOnStartup()); if (this.multipartConfig != null) { registration.setMultipartConfig(this.multipartConfig); } return registration; } }
- 注入Bean的几种方式:
- @Bean注解
- 包扫描:
- @Controller
- @Service
- @Repository
- @Component
- @Import:
- 实现ImportSelector接口的类
- 实现ImportBeanDefinitionRegistry接口
- 实现FactoryBean
<dependency> <artifactId>spring-boot-starter-jetty</artifactId> <groupId>org.springframework.boot</groupId> </dependency>
<dependency> <artifactId>spring-boot-starter-undertow</artifactId> <groupId>org.springframework.boot</groupId> </dependency>
@Configuration @ConditionalOnWebApplication @EnableConfigurationProperties({ServerProperties.class}) public class EmbeddedWebServerFactoryCustomizerAutoConfiguration { public EmbeddedWebServerFactoryCustomizerAutoConfiguration() { } @Configuration @ConditionalOnClass({Tomcat.class, UpgradeProtocol.class}) // 判断当前是否引入了Tomcat依赖 public static class TomcatWebServerFactoryCustomizerConfiguration { public TomcatWebServerFactoryCustomizerConfiguration() { }
public void customize(ConfigurableTomcatWebServerFactory factory) { ServerProperties properties = this.serverProperties; Tomcat tomcatProperties = properties.getTomcat(); PropertyMapper propertyMapper = PropertyMapper.get(); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getBasedir).whenNonNull().to(factory::setBaseDirectory); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull().as(Duration::getSeconds).as(Long::intValue).to(factory::setBackgroundProcessorDelay); this.customizeRemoteIpValve(factory); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive).to((maxThreads) -> { this.customizeMaxThreads(factory, tomcatProperties.getMaxThreads()); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive).to((minSpareThreads) -> { this.customizeMinThreads(factory, minSpareThreads); }); propertyMapper.from(this::determineMaxHttpHeaderSize).whenNonNull().asInt(DataSize::toBytes).when(this::isPositive).to((maxHttpHeaderSize) -> { this.customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull().asInt(DataSize::toBytes).to((maxSwallowSize) -> { this.customizeMaxSwallowSize(factory, maxSwallowSize); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getMaxHttpPostSize).asInt(DataSize::toBytes).when((maxHttpPostSize) -> { return maxHttpPostSize != 0; }).to((maxHttpPostSize) -> { this.customizeMaxHttpPostSize(factory, maxHttpPostSize); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getAccesslog).when(Accesslog::isEnabled).to((enabled) -> { this.customizeAccessLog(factory); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull().to(factory::setUriEncoding); properties.getClass(); propertyMapper.from(properties::getConnectionTimeout).whenNonNull().to((connectionTimeout) -> { this.customizeConnectionTimeout(factory, connectionTimeout); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive).to((maxConnections) -> { this.customizeMaxConnections(factory, maxConnections); }); tomcatProperties.getClass(); propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive).to((acceptCount) -> { this.customizeAcceptCount(factory, acceptCount); }); this.customizeStaticResources(factory); this.customizeErrorReportValve(properties.getError(), factory); }
1.SpringBoot应用启动run方法
2.SpringBoot刷新IOC容器refreshContext(建立IOC容器对象,并初始化容器,建立容器中的每个组件.若是是web应用就建立AnnotationConfigEmbeddedWebApplicationContext,不然建立默认的AnnotationConfigApplicationContext)
3.刷新建立好的容器refresh(context)
4.此时调用重写的onRefresh()方法
5.web中IOC容器会建立嵌入式的Servlet容器:createEmbeddedServletContainer()
6.获取嵌入式的Servlet容器工厂,从IOC容器中获取嵌入式Servlet容器工厂组件,当该组件存在时,Tomcat嵌入式Servlet容器工厂建立对象,后置处理器就获取全部定制器来定制Tomcat嵌入式Servlet容器的配置
7.使用Tomcat嵌入式Servlet容器工厂获取嵌入式servlet容器
8.嵌入式的Servlet容器建立对象并启动Servlet容器,先启动嵌入式的Servlet容器,再将IOC容器中对象获取出来
至此,完成IOC容器启动建立嵌入式Servlet容器tomcat
嵌入式Servlet容器:springboot
org\springframework\spring-web\5.1.9.RELEASE\spring-web-5.1.9.RELEASE.jar\META-INF\services\javax.servlet.ServletContainerInitializer
Spring的web模块中有这个文件:org.springframework.web.SpringServletContainerInitializer
3.SpringServletContainerInitializer将@HandleTypes({WebApplicationInitializer.class})标注的全部类型的类都传入到onStartup方法的Set<Class<?>>中,为WebApplicationInitializer类型的类建立实例
4.每个WebApplicationInitializer都调用本身的onStartup方法启动
5.SpringBootServletInitializer类会建立对象并执行onStartup方法启动
6.SpringBootServletInitializer执行onStartup方法会调用createRootApplicationContext建立容器服务器
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) { // 建立SpringApplicationBuilder构建器 SpringApplicationBuilder builder = this.createSpringApplicationBuilder(); builder.main(this.getClass()); 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); // 调用configure方法,子类重写该方法,将SpringBoot的主程序类传入进来 builder = this.configure(builder); builder.listeners(new ApplicationListener[]{new SpringBootServletInitializer.WebEnvironmentPropertySourceInitializer(servletContext)}); // 使用builder建立一个Spring应用 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)); } // 启动Spring应用 return this.run(application); }
7.Spring就启动成功,而且建立IOC容器app
protected WebApplicationContext run(SpringApplication application) { return (WebApplicationContext)application.run(new String[0]); }