SpringBoot内嵌Tomcat原理

一、介绍

一般我们启动web服务都需要单独的去安装tomcat,而Springboot自身却直接整合了Tomcat,什么原理呢?

二、原理

SpringBoot应用只需要引入spring-boot-starter-web中这个依赖,应用程序就默认引入了tomcat依赖,其实这主要是Tomcat本身提供的外部接口(org.apache.catalina.startup.Tomcat),使其它应用程序能够非常方便的将Tomcat嵌入到自身的应用来。
下面是从网络上找的一个自身的程序嵌入如何实现嵌入式Tomcat,达到和Springboot类似的效果:
 

<dependency>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
  </dependency>

定义一个简单的一个servlet类(提供web服务):

public class DemoServlet extends HttpServlet {
 
    private static final long serialVersionUID = 1L;
 
    @Override
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
            throws IOException, ServletException {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
 
        out.println("<!DOCTYPE html><html>");
        out.println("<head>");
        out.println("<meta charset="UTF-8" />");
        out.println("<title></title>");
        out.println("</head>");
        out.println("<body bgcolor="white">");
        out.println("<h1> 嵌入式tomcat</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

定义一个EmbeddedTomcatServer类,主程序执行入口:

EmbeddedTomcatServer类作为程序的入口,代码逻辑其实就是通过tomcat提供的外部接口类修改server.xml这个文件;

public class EmbeddedTomcatServer {
    public static void main(String[] args) throws Exception {
        //把目录的绝对的路径获取到
        String classpath = System.getProperty("user.dir");
        System.out.println(classpath);
        //new一个Tomcat
        Tomcat tomcat = new Tomcat();
 
        //插件是6或者6以前的
        //Embbedded
        //设置Tomcat的端口
        //tomcat.setPort(9090);
        Connector connector = tomcat.getConnector();
        connector.setPort(9091);
        //设置Host
        Host host = tomcat.getHost();
        //我们会根据xml配置文件来
        host.setName("localhost");
        host.setAppBase("webapps");
        //前面的那个步骤只是把Tomcat起起来了,但是没啥东西
        //要把class加载进来,把启动的工程加入进来了
        Context context = tomcat.addContext(host, "/", classpath);
 
        if (context instanceof StandardContext) {
            StandardContext standardContext = (StandardContext) context;
            standardContext.setDefaultContextXml("E:\apache-tomcat-8.5.51\conf\web.xml");
            //我们要把Servlet设置进去
            Wrapper wrapper = tomcat.addServlet("/", "DemoServlet", new DemoServlet());
            wrapper.addMapping("/embeddedTomcat");
        }
        //Tomcat跑起来
        tomcat.start();
        //强制Tomcat server等待,避免main线程执行结束后关闭
        tomcat.getServer().await();
    }
 
}

三、SpringBoot接入原理

SpringBoot嵌入Tomcat的原理其实和上面的案例是一样的,我们来看下代码:

首先进入run方法,并点击refreshContext(context)方法:

 

 如下可知,底层就是用的Tomcat类实现。

四、springboot中springmvc的初始过程

首先,在ServletWebServerApplicationContext的refresh的方法中,会调用createWebServer()方法来创建webServer org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh。

看一下createWebServer方法,首先会判断servletContext是否为空,如果为空,则会先获取ServletWebServerFactory,再进行初始化

private void createWebServer() {
   WebServer webServer = this.webServer;
   ServletContext servletContext = getServletContext();
   if (webServer == null && servletContext == null) {
      ServletWebServerFactory factory = getWebServerFactory();
      this.webServer = factory.getWebServer(getSelfInitializer());
   }
   else if (servletContext != null) {
      try {
         getSelfInitializer().onStartup(servletContext);
      }
      catch (ServletException ex) {
         throw new ApplicationContextException("Cannot initialize servlet context", ex);
      }
   }
   initPropertySources();
}

  在getSelfInitializer()中,会进行ServletContextInitializer的初始化,在getServletContextInitializerBeans中,在此方法中,通过调用new ServletContextInitializerBeans获取到一个List<ServletContextInitializer>数组,其中就包括了我们熟知的DispatchServlet和定义的Filter等等。 

private void selfInitialize(ServletContext servletContext) throws ServletException {
   prepareWebApplicationContext(servletContext);
   registerApplicationScope(servletContext);
   WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
   for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
      beans.onStartup(servletContext);
   }
}

 

  beans.onStartup过程中,进行了servlet和filter的注册,这个过程在org.springframework.boot.web.servlet.DynamicRegistrationBean#register方法中进行,会将servlet加入到servletContext中,或者将filter加入servletContext中去。

从启动日志也可以看大概的流程:

 

版权声明:本文为CSDN博主「小魏的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:总结:SpringBoot内嵌Tomcat原理_小魏的博客的博客-CSDN博客

相关文章:

springboot中springmvc的初始过程

从源码理解总结web容器、spring容器、spring mvc容器三者关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值