SpringBoot嵌入式Servlet配置原理
SpringBoot嵌入式Servlet配置原理
SpringBoot修改服务器配置
- 配置文件方式方式修改,实际修改的是ServerProperties文件中的值
server.servlet.context-path=/crud
server.port=8081
Java代码方式修改。通过实现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来创建固定的服务器。TomcatWebServerJettyWebServerNettyWebServerUndertowWebServer
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);
}
}
- 通过
this.getWebServerFactory方法创建了web服务器,通过this.getBeanFactory()获取了容器中所存在的类型为ServletWebServerFactory类型的容器,然后获取bean创建了Tomcat对象
SpringBoot嵌入式Servlet配置原理的更多相关文章
- SpringBoot嵌入式Servlet容器
SpringBoot默认是将Tomcat作为嵌入式的servlet容器. 问题: 如何修改嵌入式的servlet容器? 1)在配置文件中设置对应的属性值 server.port=8081 # Tomc ...
- SpringBoot的自动配置原理过程解析
SpringBoot的最大好处就是实现了大部分的自动配置,使得开发者可以更多的关注于业务开发,避免繁琐的业务开发,但是SpringBoot如此好用的 自动注解过程着实让人忍不住的去了解一番,因为本文的 ...
- SpringBoot之自动配置原理
我在前面的Helloworld的程序中已经分析过一次,配置原理了: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@En ...
- 面试题: SpringBoot 的自动配置原理
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 3.Spring Boot 的自动配置原理 package com.mmall; import org. ...
- SpringBoot的自动配置原理
一.入口 上篇注解@SpringBootApplication简单分析,说到了@SpringBootApplication注解的内部结构, 其中@EnableAutoConfiguration利用En ...
- SpringBoot的启动配置原理
一.启动流程 创建SpringApplication对象 public class SpringApplication { public SpringApplication(Class... prim ...
- 18、配置嵌入式servlet容器(2)
使用其他Servlet容器 -Jetty(长连接) -Undertow(不支持jsp) 替换为其他嵌入式Servlet容器 默认支持: Tomcat(默认使用) Jetty: <depend ...
- SpringBoot源码学习系列之嵌入式Servlet容器
目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...
- SpringBoot自动配置原理
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...
随机推荐
- 微信小程序点击图片放大
WXML: <view class='imgList'> <view class='imgList-li' wx:for='{{imgArr}}'> <image cla ...
- Cannot create PoolableConnectionFactory (Could not create connection to database server.)
是由于mysql驱动版本太低导致. 本人 jdk版本是1.8.0_211,mysql版本是8.0.17,mysql-connector-java版本是5.1.39, 后来把mysql-connecto ...
- 用K-Means聚类分析做客户分群
聚类指的是把集合,分组成多个类,每个类中的对象都是彼此相似的.K-means是聚类中最常用的方法之一,它是基于点与点距离的相似度来计算最佳类别归属. 在使用该方法前,要注意(1)对数据异常值的处理:( ...
- git 远程托管
1.创建别名 git remote add orgin(别名) url 2.推入云端 git push 别名 master(分支) git push 别名 dev 3.克隆(默认只有master分支) ...
- 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发
<ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-tr ...
- Hystrix 监控数据聚合 Turbine【Finchley 版】
原文地址:https://windmt.com/2018/04/17/spring-cloud-6-turbine/ 上一篇我们介绍了使用 Hystrix Dashboard 来展示 Hystrix ...
- 图解kubernetes调度器SchedulerExtender扩展
在kubernetes的scheduler调度器的设计中为用户预留了两种扩展机制SchdulerExtender与Framework,本文主要浅谈一下SchdulerExtender的实现, 因为还有 ...
- HDU Queuing(递推+矩阵快速幂)
Queuing Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Docker Swarm 从入门到放弃
准备工作 我本机是macOS,所以我直接安装了docker desktop,其中包含了docker-machine,不用单独安装. 安装docker主机驱动 我在网上很多人提到了使用virtualbo ...
- SpringMVC进阶(二)
一.高级参数绑定 1.1. 绑定数组 Controller方法中可以用String[]接收,或者pojo的String[]属性接收.两种方式任选其一即可. /** * 包装类型 绑定数组类型,可以使用 ...