tomcat如何和springboot交互的?
今天看了tomcat相关资料,发现tomcat主要工作是serversocket监听客户端请求,然后解析http请求再封装request,response再去请求服务端的servlet的service方法,但是我们现在用的sprongboot或spring,都不用写servlet了,那么springboot是如何集成servlet的?tomcat如何和springboot交互的?
回答
你是不用写了,但是框架自己写了,就是 DispatcherServlet,然后再通过反射调用你写在 Controller 里面的方法。也就是 tomcat 是和 spring mvc 框架交互,然后 spring mvc 再调用你写的东西。所以你不需要写 servlet 了。你连这个都不明白的话,感觉你是没有系统的学习过。而是直接上手 springboot。
spring mvc本身就是个servlet,具体代码可以看org.springframework.web.servlet.DispatcherServlet,tomcat接受请求后,绝大多数请求会直接交给DispatherServlet处理,而根据URI分发给具体的Controller方法,其实是在DispatherServlet内部的逻辑,可以简单理解为spring mvc自定义了一个servlet,然后在这个servlet内部又设计了一套处理逻辑暴露给开发者。
至于spring boot为什么不需要额外部署tomcat,因为spring boot内置了一个tomcat,具体代码可以看org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh,这是一个spring上下文,在启动spring容器时会调用这个onRefresh()方法,它里面有个createWebServer()方法,就是创建一个tomcat实例,并且把自己的各种资源路径设置给tomcat然后启动它
说的比较详细严格来说是抽象成了一个spring-boot-starter-web组件,可以替换成其他实现了spring-boot-starter-web接口的插件。比如我们就用undertow替换掉了tomcat,只需要把项目工程的spring-boot-starter-web依赖替换成spring-boot-starter-undertow即可
spring boot的工程默认的依赖不就有个spring-boot-starter-web吗?这玩意默认就会依赖tomcat。于是等于spring boot内嵌了一个tomcat作为servlet的运行容器,打到jar包里面做成了一个可以自启动的程序。
同理,你可以把这个spring-boot-starter-web依赖换成其他servlet容器,比如spring-boot-starter-jetty或者性能更优秀的spring-boot-starter-undertow,就可以替换成其他servlet容器,具体文档参考spring boot官方文档: https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/reference/htmlsingle/#using-boot-starter
回复 @Jordan裔 : Spring boot摒弃了那一堆xml,而是通过注解生成对应的xml配置。spring boot通过注解生成servlet的。你还可以看看这些教程你就明白了: https://www.baeldung.com/register-servlet但是我们用springboot的时候没有写servlet啊,tomcat是如何调用我们服务的?
spring-boot-autoconfigure 包下面有自动配置类,应该与这些自动配置类有关系,包括与其他框架整合时也会用到的。
其实关键的是 servlet 3,在 servlet 3 之后可以直接使用 @WebServlet 和 @WebFilter 来声明 servlet 和 filter,这样一来就不再需要在 web.xml 中配置 DispatcherServlet 了
哈哈哈哈,虽然你没写,但是spring帮你写了啊,你写的controller就是spring的servlet在调用啊,哈哈哈哈哈哈哈哈,你为什么要哈哈哈哈?spring boot内嵌了tomcat 使用约定大于配置的方式,帮你写好了。但是底层任然是servlet那套逻辑,只是通过反射来调用你定义的方法。
框架帮你写了,底层已经帮你封装好了
代码阅读路线 : refresh --》 onfresh --》 createWebServer。在servlet 3.1 的规范中,web.xml 的左右,可以使用注解进行替代。可以看一下 ServletContainerInitializer 这个类是怎么被实现的。
首先在你的工程里面肯定得有个main方法,main方法里面肯定会调用一个run方法,用于启动springboot。
在run方法里面肯定又会 调用一些initialize的方法,包括加载配置,启动内嵌的tomcat等。
tomcat启动流程中肯定又会扫苗它关心的配置,相当于以前的web.xml,现在可能是通过某个java类来实现的。这里面内置的类会放出很多handle出来,你可以覆盖默认的实现来达到自定义的目的。tomcat肯定会读到一个配置,就是指定某个servlet 和 / 的映射关系。意味着这个servlet会处理所有请求。
同时在springboot启动过程中还会扫描带有@Container的类,并扫描其方法的mapping配置,缓存到 urlmapping中。
当启动完成,这个时候默认的8080端口已经监听好。请求过来,tomcat就会解析http协议内容封装成servlet里面涉及到的request response application session等对象。并调用刚才监听所有请求的servlet中的service方法。这个方法的实现大概就是在urlmapping中找到对应的类和方法及其参数,并将请求中的参数对应上,调这个方法。
最后这个方法就是你自己的实现。