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. Java 利用Map集合计算一个字符串中每个字符出现的次数

    步骤分析 1.给出一串字符串,字符串中可以包含字母.数字.符号等等. 2.创建一个Map集合,key是字符串中的字符,value是字符的个数. 3.遍历字符串,获取每一个字符. 5.使用获取到的字符, ...

  2. ElasticSearch安装中文分词器IKAnalyzer

    # ElasticSearch安装中文分词器IKAnalyzer  本篇主要讲解如何在ElasticSearch中安装中文分词器IKAnalyzer,拆分的每个词都是我们熟知的词语,从而建立词汇与文档 ...

  3. hdfs断电报错解决

    一,/home/hadoop/tmp/dfs/name/current 目录下查看文件二,1.stop hadoop所有的服务;2.重新格式化namenode即可: hadoop根目录下: hadoo ...

  4. 若依框架. 仿ThymeLeaf前端SelectDictLable方法

    在framework项目下新增所需服务

  5. redis 5种类型

    redis可以不严谨的看成: redis: { name: value, name: value, } value的数据类型: 1.字典 2.列表 3.字符串 4.集合 5.有序集合 注意: redi ...

  6. CDH大数据平台搭建终极版

    经过无数次的失败,终于将CDH安装到两台普通的笔记本电脑上,主要失败原因有以下几点: 不熟悉安装过程,官方给出的安装方法有三种,所以都尝试了一遍,浪费了大量时间,所以有时候方法多不见得是一件好事. 安 ...

  7. .NetCore自定义WebAPI返回Json的格式大小写的三种方式

    .NetCore的Controller/WebAPI可以帮我们将返回结果自动转换为Json格式给前台,而且可以自由设定格式(大写.小写.首字母大写等),我总结了三种方法,对应三种灵活度,供大家参考 ( ...

  8. Maven的学习之路1

    对于下列这段Maven的命令行有不懂之处,在zgmzyr的博客上得到了解释.非常感谢这位博友,写在自己的随笔上以便查看和修改. 1. 创建项目 $ mvn archetype:generate -Dg ...

  9. Python的条件控制及循环

    一.条件控制: 1.If语句的使用: Python中if语句的一般形式如下所示: 上图中: 如果 "score>=90" 为 True 将执行 "print(‘优秀 ...

  10. 龙芯 fedora28 安装指南

    版权声明:原创文章,未经博主允许不得转载 关于硬件 龙芯3号的板子安装系统都差不多,我分别在 Lemote A1310 和 Lemote A1901 上都尝试过. 本文主要依据 Lemote A190 ...