使用SpringBoot内置web服务器

目录
  • 一、SpringBoot默认web服务器?
  • 二、如何配置当前web容器?
  • 三、内嵌Web服务器如何切换(从tomcat到jetty)?
  • 四、Web容器怎么自动配置?
  • 五、web容器启动源码解析?
  • 六、SpringBoot内置服务器不使用SPI机制特别说明?

本文介绍SpringBoot内置web服务器。知识点有SpringBoot默认web服务器;如何配置当前web容器;内嵌Web服务器如何切换(从tomcat到jetty);Web容器怎么自动配置;web容器启动源码解析;SpringBoot内置服务器不使用SPI机制特别说明。

一、SpringBoot默认web服务器?

在SpringBoot中采用的默认web服务器是Tomcat,要了解为什么是Tomcat可从源码入手。

对于web服务器的配置,也是在自动配置中找,前面学习了SpringBoot自动配置WebMVC的知识,可以推测对于Web服务器的配置应该也是在一个自动配置类当中进行的,那么可以去/META-INF/spring.factories文件找一下WebMVC的自动配置,在这个自动配置内可以间接找到关于Web服务器的配置。

org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\

在上面SpringBoot包的目录找到这个路径下的Web服务器自动配置类。

这个Web服务器的自动配置类,我们可以看到这个配置类支持3种web服务器(Tomcat,Jetty,Undertow),具体要配置哪种服务器由ServletWebServerFactoryConfiguration来决定,同时这里还定义了一个顺序,依次是Tomcat->Jetty->Undertow。

那要选择哪种服务器呢?看ServletWebServerFactoryConfiguration。

在这个web服务器工厂配置类中,分别对上述三种服务器进行了定义:

对Tomcat定义:判断环境中是否引入了Tomcat所需的依赖Servlet.class, Tomcat.class, UpgradeProtocol.class,同时用户没有自己进行Web服务器配置(比如自己通过实现ServletWebServerFactory接口进行手动配置web服务器),那么这个Tomcat服务器就会生效。

对Jetty定义:所需要的依赖有Servlet.class, Server.class, Loader.class, WebAppContext.class

对Undertow定义:所需要的依赖有Servlet.class, Undertow.class, SslClientAuthMode.class

那么问题来了,SpringBoot如果这几种都有,那是怎么选择呢?从ServletWebServerFactoryAutoConfiguration配置类

@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
      ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
      ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
      ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration 

通过@Import就可以看出这里定义了一个顺序,依次是Tomcat->Jetty->Undertow,意思就是当环境中有Tomcat满足的依赖时就会优先使用Tomcat,依次往后推。

而一般情况下,在SpringBoot依赖中默认就已经引入tomcat的依赖,因此这里对于tomcat来说一般情况下会恒成立,那么Tomcat就会一直作为恒成立条件被SpringBoot首选为默认服务器。

二、如何配置当前web容器?

想要配置当前Web容器,可以通过yml配置让SpringBoot自动加载解析修改配置,也可以通过提供自定义的@Bean方法忽略SpringBoot自动配置采用手动配置方式。

为什么是通过@Bean提供ServletWebServerFactory和WebServerFactoryCustomizer的Bean交给Spring就可以跳过SpringBoot的自动web服务器配置呢?可从源码分析如下:

对于WebServerFactoryCustomizer在上面ServletWebServerFactoryConfiguration配置类Factory配置Tomcat,Jetty时在注解上会判断存过存在自己手动添加的ServletWebServerFactory则不再进行自动配置:

对于WebServerFactoryCustomizer则在ServletWebServerFactoryAutoConfiguration服务器自动配置类加载时,如果存在自己定义的WebServerFactoryCustomizer,那么就会触发一个WebServerFactoryCustomizerBeanPostProcessor后置处理器,在这个后置处理器中会遍历这些WebServerFactoryCustomizer并且执行内部customize方法,从而跳过自动配置,转为进行自定义配置:

三、内嵌Web服务器如何切换(从tomcat到jetty)?

上面通过源码可以知道一般情况下,Tomcat会一直作为恒成立条件被SpringBoot首选为默认服务器。

但是我们如果不想用Tomcat作为默认服务器,例如想切换为Jetty,那么我们应该怎么办呢?

我们可以把Tomcat的相关依赖在pom.xml中的spring-boot-starter-web中剔除掉,使环境不再拥有Tomcat依赖,同时加入Jetty的依赖那么就能使Jetty作为满足条件被SpringBoot选择了。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 剔除Tomcat -->
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 加入jetty -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

这样,SpringBoot重新启动后就会切换为Jetty服务器了。

四、Web容器怎么自动配置?

对于Web容器的自动配置,以Tomcat未来可以看上面提到的TomcatServletWebServerFactory,这是通过@Bean自动注入一个Tomcat的工厂类:

这个工厂类内部会对Tomcat进行一些初始化操作,最重要的操作在getWebServer方法内:

首先这个类是SpringBoot包提供的,用的是最底层的tomcat实例进行配置(通过new Tomcat的方式,而这个Tomcat是tomcat源码包的一个实例类 package org.apache.catalina.startup),具体的配置细节不做描述,主要对端口,协议,tomcat组件对象等进行初始化并封装:

将要发布的Web应用信息Context初始化到tomcat中:

对初始化好的tomcat进行封装并启动:

最后将这个tomcat对象封装为一个TomcatWebServer对象供SpringBoot启动时调用。

综上,web容器的自动配置,实际上是SpringBoot通过创建原生Tomcat对象,对这个对象进行端口,协议,组件等初始化,并且将Web应用信息Context对象封装到这个tomcat对象中,然后Web应用信息配置生命周期监听生效后启动tomcat,最后将这个过程

封装到一个WebServer对象中供SpringBoot启动时调用。

五、web容器启动源码解析?

SpringBoot是什么时候运行了一个web服务器呢?这个要从SpringBootApplication.run()方法进行分析。以tomcat为例按照上面提到的,这个启动过程应该会调用到TomcatServletWebServerFactory.getWebServer方法获取这么一个tomcat实例。

调用链可看下面图示:

SpringBootApplication.run():

context = createApplicationContext():创建Context环境,这个方法内会根据当前环境初始化不同的Context,如果是Web环境则会初始化出AnnotationConfigServletWebApplicationContext:

初始化AnnotationConfigServletWebApplicationContext之后,在构造函数调用这个context的refresh方法-->onRefresh方法:

调用onRefresh方法,就会调用到ServletWebServerApplicationContext的onRefresh方法,在这个方法内,就对web服务器进行了创建操作createWebServer():

在createWebServer()方法中,会判断是外置还是内置方式发布应用,分别进行不同的逻辑操作。我们这里以内置来学习:

这样,SpringBoot启动时在创建Web服务器时,就执行到了getWebServer的操作,然后再对Web服务器进行创建,初始化和启动操作。

综上:在SpringBoot的run启动时,会判断当前所处环境。

如果是Web环境则通过创建一个ServletWebServerApplicationContext,执行构造函数的refresh方法,在refresh方法内重写onRefresh方法,执行创建createWebServer()方法,这个方法会根据当前应用是内置还是外置发布方式来决定以何种方式获取web服务器。

如果是内置方式则通过TomcatServletWebServerFactory工厂类来获取一个首选的web服务器,然后进行服务器的初始化配置,应用加载生效以及服务器启动的操作。

六、SpringBoot内置服务器不使用SPI机制特别说明?

最后还有一个结论要记住:对于SpringBoot内置服务器不会通过SPI的机制(官网也有特别说明),因为SpringBoot内置服务器是SpringBoot自己帮我们创建了web服务器来发布应用,不使用SPI机制的目的就是尽可能减少内置和外置web服务器可能存在的冲突,让web应用由SpringBoot自己来管理。详细原因和原理这里不做研究。

至此,关于SpringBoot内置服务器的相关知识解析就到此了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 基于springboot搭建的web系统架构的方法步骤

    从接触springboot开始,便深深的被它的简洁性深深的折服了,精简的配置,方便的集成,使我再也不想用传统的ssm框架来搭建项目,一大堆的配置文件,维护起来很不方便,集成的时候也要费力不少.从第一次使用springboot开始,一个简单的main方法,甚至一个配置文件也不需要(当然我是指的没有任何数据交互,没有任何组件集成的情况),就可以把一个web项目启动起来,下面总结一下自从使用springboot依赖,慢慢完善的自己的一个web系统的架构,肯定不是最好的,但平时自己用着很舒服. 1. 配

  • SpringBoot深入理解之内置web容器及配置的总结

    前言 在学会基本运用SpringBoot同时,想必搭过SSH.SSM等开发框架的小伙伴都有疑惑,SpringBoot在spring的基础上做了些什么,使得使用SpringBoot搭建开发框架能如此简单,便捷,快速.本系列文章记录网罗博客.分析源码.结合微薄经验后的总结,以便日后翻阅自省. 正文 使用SpringBoot时,首先引人注意的便是其启动方式,我们熟知的web项目都是需要部署到服务容器上,例如tomcat.weblogic.widefly(以前叫JBoss),然后启动web容器真正运行我

  • 运用springboot搭建并部署web项目的示例

    前言 一直以来都是用springmvc+mybatis进行后端接口开发工作,最近闲来无事,根据现有功能需求,用springboot+mybatis部署一套简单的web项目. 所用工具 IntelliJ IDEA 2018.1.4 JDK 1.8 apache-tomcat-8.0.50 所解决的问题 1.如何用idea创建springboot项目 2.如何进行 服务器.数据库.mybatis.视图解析器的配置 3.如何使用mybatis generator 自动生成代码 4.如何使用multip

  • 使用SpringBoot内置web服务器

    目录 一.SpringBoot默认web服务器? 二.如何配置当前web容器? 三.内嵌Web服务器如何切换(从tomcat到jetty)? 四.Web容器怎么自动配置? 五.web容器启动源码解析? 六.SpringBoot内置服务器不使用SPI机制特别说明? 本文介绍SpringBoot内置web服务器.知识点有SpringBoot默认web服务器:如何配置当前web容器:内嵌Web服务器如何切换(从tomcat到jetty):Web容器怎么自动配置:web容器启动源码解析:SpringBo

  • PHP5.4内置web服务器

    PHP是一种脚本语言,它需要PHP解释器来分析运行PHP文件.当把PHP做为CGI服务Web请求时,它需要被嵌入到某种Web服务器里,最常见的是集成到Apache或IIS里,这就是说,在使用PHP前,你需要安装Apache或IIS,并且正确的配置它们和PHP集成的参数.虽然这种配置已经很规范,文档非常丰富,但我们还是经常在安装Apache和PHP集成时遇到问题,而且,有时候我们只想测试一个简单的PHP特征,不想就为此安装.启动Apache服务. 但据官方文档上说,这个内置的Web服务器只是提供开

  • PHP 内置WEB服务器的简单使用

    在很多时候,我们需要简单的运行一个小 demo 来验证一些代码或者轮子是否可用,是否可以运行起来,但是去配 nginx 或者 apache 都很麻烦,其实,PHP CLI 已经提供了一个简单的测试服务器,我们直接就可以运行起来进行简单的一些测试工作. 直接启动一个内置服务器 php -S localhost:8081 直接使用 -S 命令选项,然后指定地址及端口号,我们就可以运行起来一个 PHP 内置的简易WEB服务器.默认情况下,这个地址会找当前目录下的 index.php 或 index.h

  • PHP5.4起内置web服务器使用方法

    PHP是一种脚本语言,它需要PHP解释器来分析运行PHP文件.当把PHP做为CGI服务Web请求时,它需要被嵌入到某种Web服务器里,最常见的是集成到Apache或IIS里,这就是说,在使用PHP前,你需要安装Apache或IIS,并且正确的配置它们和PHP集成的参数.虽然这种配置已经很规范,文档非常丰富,但我们还是经常在安装Apache和PHP集成时遇到问题,而且,有时候我们只想测试一个简单的PHP特征,不想就为此安装.启动Apache服务. 但据官方文档上说,这个内置的Web服务器只是提供开

  • 浅谈springboot内置tomcat和外部独立部署tomcat的区别

    前两天,我去面了个试,面试官问了我个问题,独立部署的tomcat跟springboot内置的tomcat有什么区别,为什么存在要禁掉springboot的tomcat然后将项目部署到独立的tomcat当中? 我就想,不都一个样?独立部署的tomcat可以配置优化?禁AJP,开多线程,开nio?而且springboot内置的tomcat多方便,部署上服务器写个java脚本运行即可.现在考虑下有什么条件能优于内置tomcat的. 1.tomcat的优化配置多线程?内置的也可以配置多线程 server

  • SpringBoot内置tomcat启动原理详解

    前言 不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcat在springboot是怎么启动的呢? 内置tomcat 开发阶段对我们来说使用内置的tomcat是非常够用了,当然也可以使用jetty. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-bo

  • SpringBoot内置tomcat调优测试优化

    问题 怎么配置springBoot 内置tomcat,才能使得自己的服务效率更高呢? 基础配置 Spring Boot 能支持的最大并发量主要看其对Tomcat的设置,可以在配置文件中对其进行更改.我们可以看到默认设置中,Tomcat的最大线程数是200,最大连接数是10000. 这个不同SpringBoot 版本可能有所细微差别.本文测试基于Springboot 2.0.7.RELEASE 默认配置 /** * Maximum amount of worker threads. */ priv

  • SpringBoot 内置工具类的使用

    目录 断言 对象.数组.集合 ObjectUtils StringUtils CollectionUtils 文件.资源.IO 流 FileCopyUtils ResourceUtils StreamUtils 反射.AOP ReflectionUtils AopUtils AopContext 断言 断言是一个逻辑判断,用于检查不应该发生的情况 Assert 关键字在 JDK1.4 中引入,可通过 JVM 参数-enableassertions开启 SpringBoot 中提供了 Assert

  • SpringBoot内置数据源的持久化与解决方案

    目录 数据层解决方案 与SQL有关的解决方案 SpringBoot提供了3种内嵌的数据源对象供开发者选择 内置持久化解决方案 Springboot内置数据库 数据层解决方案 SQL NoSQL 与SQL有关的解决方案 现有数据层解决方案技术选型 Druid + MyBatis-Plus + MySQL 数据源:DruidDataSource 持久化技术:MyBatis-Plus / MyBatis 数据库:MySQL SpringBoot提供了3种内嵌的数据源对象供开发者选择 HikariCP

  • Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)

    在 Node.JS 中进行端口扫描还是比较方便的,一般会有广播和轮询两种方式.即使用广播和扫描,使用广播发出的消息有时会被路由器屏蔽,所以并不可靠. 使用node.js中的net模块,可以直接尝试向目录主机的某个端口进行连接,如果能建立连接,则说明该地址存在服务器. var socket = new Socket() socket.connect(port, host) socket.on('connect', function() { //找到port 和 host 地址 }) 所以只要进行2

随机推荐