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来创建固定的服务器。

    • 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);
}
}
  • 通过this.getWebServerFactory方法创建了web服务器,通过this.getBeanFactory()获取了容器中所存在的类型为ServletWebServerFactory类型的容器,然后获取bean创建了Tomcat对象

SpringBoot嵌入式Servlet配置原理的更多相关文章

  1. SpringBoot嵌入式Servlet容器

    SpringBoot默认是将Tomcat作为嵌入式的servlet容器. 问题: 如何修改嵌入式的servlet容器? 1)在配置文件中设置对应的属性值 server.port=8081 # Tomc ...

  2. SpringBoot的自动配置原理过程解析

    SpringBoot的最大好处就是实现了大部分的自动配置,使得开发者可以更多的关注于业务开发,避免繁琐的业务开发,但是SpringBoot如此好用的 自动注解过程着实让人忍不住的去了解一番,因为本文的 ...

  3. SpringBoot之自动配置原理

    我在前面的Helloworld的程序中已经分析过一次,配置原理了: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@En ...

  4. 面试题: SpringBoot 的自动配置原理

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 3.Spring Boot 的自动配置原理 package com.mmall; import org. ...

  5. SpringBoot的自动配置原理

    一.入口 上篇注解@SpringBootApplication简单分析,说到了@SpringBootApplication注解的内部结构, 其中@EnableAutoConfiguration利用En ...

  6. SpringBoot的启动配置原理

    一.启动流程 创建SpringApplication对象 public class SpringApplication { public SpringApplication(Class... prim ...

  7. 18、配置嵌入式servlet容器(2)

    使用其他Servlet容器 -Jetty(长连接) -Undertow(不支持jsp) 替换为其他嵌入式Servlet容器   默认支持: Tomcat(默认使用) Jetty: <depend ...

  8. SpringBoot源码学习系列之嵌入式Servlet容器

    目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...

  9. SpringBoot自动配置原理

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...

随机推荐

  1. 网络流 - 最大流构图入门 bzoj 1305

    一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲.有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”).每个男孩 ...

  2. 村庄之间建立邮局 - 区间 dp

    There is a straight highway with villages alongside the highway. The highway is represented as an in ...

  3. hdu - 4990

    Read the program below carefully then answer the question.    #pragma comment(linker, "/STACK:1 ...

  4. 成功填坑! Java引入QQ登录时,AccessToken [accessToken=, expireIn=];

    主要就是会一直进入下面这一行,也就是accessTokenObj.getAccessToken().equals("") 此时前端显示如下 AccessToken [accessT ...

  5. springboot的yml不显示的原因

    首先排除插件原因 1 安装好插件Ctrl+Alt+S 2 查看修改的application.yml是什么格 在yaml格式中添加*.yaml和*.yml 3 查看maven是否配置完善

  6. linux运行tomcat报错SEVERE: Unable to process Jar entry [avassist xxxx.class]

    tomcat的版本过低换成apache-tomcat-7.0.56以上的高版本的就可以了

  7. Java中SMB的相关应用

    目录 SMB 服务操作 Ⅰ SMB简介 Ⅱ SMB配置 2.1 Windows SMB Ⅲ 添加SMB依赖 Ⅳ 路径格式 Ⅴ 操作共享 Ⅵ 登录验证 SMB 服务操作 Ⅰ SMB简介 ​ SMB(全称 ...

  8. 龙芯 Fedora 28 设置 VNC

    系统为龙芯版Fedora28 (床28) Fedora防火墙默认阻止了VNC所需的端口的访问,导致VNC客户端一直无法连接. 安装VNC Server sudo dnf install tigervn ...

  9. Centos7安装 Anaconda + jupyter notebook

    一.安装Anaconda 1 下载Anaconda安装脚本 为了避免漫长的等待,镜像源选择国内的清华镜像源,镜像源地址:https://mirrors.tuna.tsinghua.edu.cn/ana ...

  10. [SDOI2011]染色(树链剖分)

    [SDOI2011]染色(luogu) Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段 ...