一.web项目为什么要有web.xml
1.web项目通常打成war包,放在tomcat的webapps下面,启动tomcat
2.web.xml学名叫部署描述符文件,是在Servlet规范中定义的,tomcat等web服务器通过配置文件web.xml找相应的servlet,因为统一配置在一起,方便集中管理。web.xml主要用来配置Servlet、Listener、Filter等
3.什么是web服务器?简单来讲,web服务器的作用就是解析客户端http请求,并返回服务端的数据,所以,只要能处理http请求返回,其实就是web服务器,比如netty等。什么是Servlet?Servlet就是java语言用来处理http协议网络请求的一套规范,tomcat完整的实现了Servlet规范

二.怎么做到没有web.xml的
1.因为是servlet规范,所以肯定要规范升级,servlet3.0升级的新特性
可以通过ServletContext类中的addServlet、addListener、addFilter方法设置servlet、listener、filter(或者通过@WebServlet,@WebListener,@WebFilter注解方式,如果不用框架,单纯servlet方式,注解方式挺好,web服务器从原来的加载web.xml变成了加载这些注解)
2.ServletContext 对象又是怎么调用的呢?
先说具体的实现,web项目要在路径:项目名XXX\src\main\resources\META-INF\services\下有这样一样javax.servlet.ServletContainerInitializer文件,文件内容是实现ServletContainerInitializer接口的类全名称,没错,这些东西是死的,可以理解这就是规范。
web服务器在启动时,会去查找这个配置文件,取到类名,通过反射的方式来加载和实例化ServletContainerInitializer对象;然后调用接口方法onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext),在servletContext中设置addServlet、addListener、addFilter,从而实现了web服务器-->自己本地项目ServletContainerInitializer-->servlet、listener、filter
其实这就是spi(Service Provider Interface),一种服务发现机制
Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制;
对于服务调用方C来说,将装配的控制权转移到程序之外(服务提供方P),好处就是解耦;
感觉也有点类似于钩子方法或者回调方法的套路
三.spring中如何做的
为了区别,spring没有在ServletContainerInitializer中处理servlet,而是重新提供WebApplicationInitializer接口,public interface WebApplicationInitializer {void onStartup(ServletContext var1) throws ServletException;}通过实现这个接口,设置ServletContext
那怎么样调用到WebApplicationInitializer类中的呢?通过ServletContainerInitializer+注解@HandlesTypes类,@HandlesTypes的原理,就是加载包下面所有的class文件,判断是不是@HandlesTypes注解类所关心的类(非接口和抽象类),如果是放在set集合中,然后执行onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)方法,取到所关心类WebApplicationInitializer的class信息,反射实例化出WebApplicationInitializer对象,调用onStartup(ServletContext var1) ,这样就实现了ServletContainerInitializer-->WebApplicationInitializer的过程
四.springboot中如何做的,又是怎样内嵌tomcat的?

springboot提供了一个新的接口org.springframework.boot.web.servlet.ServletContextInitializer(既没有用serlvet3.0规划中的ServletContainerInitializer,又没有用spring-web模板中提供的WebApplicationInitializer,但功能类似,都是提供一个回调接口onStartup(ServletContext servletContext),通过这个钩子似的回调接口来设置servletContext)