为什么Spring boot中,没有web.xml?
1.Springboot自动配置Servlet容器
我们上文发现,spring其实也需要实现WebApplicationInitializer接口,覆写onStartup方法。但是在springboot中,我们发现并不需要我们自己实现接口。
Spring Boot 的自动配置:Spring Boot 是 Spring
生态中的一个项目,它提供了自动配置机制,可以自动配置 Servlet
容器、DispatcherServlet 等,并且不需要 web.xml
文件。以便你专注于编写应用程序的业务逻辑而不必关心底层配置。
默认情况下,Spring Boot 的
DispatcherServlet
会映射到根路径 "/*",这意味着所有的 HTTP 请求都会经过DispatcherServlet
进行处理。如果需要修改DispatcherServlet
的配置,可以通过 Spring Boot 提供的一些属性来实现。可以通过在
application.properties
或application.yml
文件中添加相应的属性server.servlet.context-path=/myapp
或
server: servlet: context-path: /myapp
在Spring
Boot中,DispatcherServlet
是一个核心组件,它负责处理所有的HTTP请求。Spring
Boot通过自动配置的方式简化了DispatcherServlet
的注册和配置过程。下面是Spring
Boot自动注册DispatcherServlet
的详细流程:
见名知意我们也知道它的作用是:DispatcherServlet ----Auto(自动)----Configuration(配置)
2. DispatcherServletAutoConfiguration
Spring
Boot使用@EnableAutoConfiguration
注解来启用自动配置,其中包括了DispatcherServletAutoConfiguration
类。该类负责配置和注册DispatcherServlet
。
1 |
|
2.1 条件注解
在DispatcherServletAutoConfiguration
类上,多个条件注解用于确保该配置仅在特定条件下生效:
@ConditionalOnClass
:只有在类路径上存在Servlet
和DispatcherServlet
时才会生效。@ConditionalOnWebApplication
:只有在当前应用类型为Servlet Web应用时才会生效。
3. 注册
DispatcherServlet
Bean
在DispatcherServletAutoConfiguration
中,会创建和注册一个DispatcherServlet
。通常,这通过@Bean
方法来实现。
1 |
|
4. 注册 DispatcherServletRegistrationBean
除了创建DispatcherServlet
Bean,Spring
Boot还会注册ServletRegistrationBean
,将DispatcherServlet
映射到特定的URL模式(默认是“/”)。
见名知意我们也知道它的作用是:DispatcherServlet ----Registration(登记,注册)----Bean
1 |
|
我们可以看到:
1 |
|
DispatcherServletRegistrationBean
体系结构
我们发现它最终也是实现了ServletContextInitializer
接口。
1 |
|
4.1 RegistrationBean
RegistrationBean
实现了ServletContextInitializer
,之后调用register方法,这个是抽象方法,由子类DynamicRegistrationBean
实现:
1 |
|
4.2 DynamicRegistrationBean
DynamicRegistrationBean
继承了RegistrationBean
,之后调用addRegistration方法,这个是抽象方法,由子类ServletListenerRegistrationBean
实现:
1 |
|
4.3 ServletListenerRegistrationBean
子类ServletRegistrationBean
的addRegistration方法
1 |
|
servletContext.addServlet():Servlet3.0+的特性,将servlet添加到容器
5.ServletContextInitializerBeans
上面我们已经有了DispatcherServletRegistrationBean,只要我们注册该类,SpringBoot就会执行一系列操作配置好我们DispathcerServlet,但是什么时候才会触发ServletContextInitializer
的onStartup
方法呢?
在 Spring Boot 中,ServletContextInitializerBeans
是一个帮助类,用于收集和管理所有实现了
ServletContextInitializer
接口的
Bean。存储在自身的集合中。
- 收集
ServletContextInitializer
Bean: 它会从应用上下文中收集所有实现了ServletContextInitializer
接口的 Bean。 - 排序和管理: 收集到的
ServletContextInitializer
Bean 可以按照一定的顺序进行管理,确保它们按正确的顺序执行。
这些 Bean 可以在应用程序启动时对 ServletContext
进行编程式配置。再看一下这图:
最终也就是我们的DispatcherServletRegistrationBean
。
1 |
|
ServletContextInitializerBean获取所有实现了ServletContextInitializer接口的类。存储到initializers集合。
可以看到,实现了ServletContextInitializer的不止是Servlet类型的,还有Listener、Filter类型的。
因为他们都需要动态添加到web容器中
6.ServletWebServerApplicationContext
ServletContextInitializerBeans
已经收集和调用所有实现了
ServletContextInitializer
接口的 Bean。
ServletWebServerApplicationContext
是 Spring Boot 中用于
Servlet 环境的 ApplicationContext
实现。它是
GenericWebApplicationContext
的子类,专门用于创建和管理嵌入式 Servlet 容器(如 Tomcat、Jetty 或
Undertow)。
6.1 工作流程
以下是 ServletWebServerApplicationContext
的工作流程:
- 初始化嵌入式 Servlet 容器:
- 在
onRefresh()
方法中,ServletWebServerApplicationContext
会调用createWebServer()
方法初始化嵌入式 Servlet 容器。 createWebServer()
方法会实例化WebServerFactory
(如TomcatServletWebServerFactory
)来创建具体的嵌入式容器实例。
- 在
- 启动嵌入式 Servlet 容器:
- 在初始化完成后,调用
webServer.start()
启动嵌入式容器。 start()
方法会启动容器,并将上下文路径、Servlet
、Filter
等注册到容器中。
- 在初始化完成后,调用
- 注册
Servlet
和Filter
:- 在嵌入式容器启动过程中,
ServletWebServerApplicationContext
会扫描并注册所有实现了Servlet
、Filter
或ServletContextListener
的 Bean。 - 它还会根据配置文件或注解来注册
DispatcherServlet
、ErrorPage
等。
- 在嵌入式容器启动过程中,
- 关闭嵌入式 Servlet 容器:
- 在
close()
方法中,ServletWebServerApplicationContext
会调用webServer.stop()
关闭嵌入式容器,释放相关资源。
- 在
6.2 代码实现
6.2.1 onRefresh()
1 |
|
6.2.2 createWebServer()
1 |
|
6.2.3 getSelfInitializer()
1 |
|
我们看到:通过
getServletContextInitializerBeans()
方法返回所有实现ServletContextInitializer
接口的实现类,循环调用它们的onStartup
方法。
6.2.4 getServletContextInitializerBeans()
1 |
|
getServletContextInitializerBeans
方法在 Spring Boot
中的作用是获取所有实现了 ServletContextInitializer
接口的
Bean,也就是ServletContextInitializerBean
的集合。
7.启动流程总结
Spring Boot通过
DispatcherServletAutoConfiguration
类简化了DispatcherServlet
的注册流程。自动配置类根据条件注解自动加载并配置DispatcherServlet(DispatcherServletBean)
和ServletRegistrationBean(DispatcherServletRegistrationBean)
。再通过
ServletContextInitializerBeans
类收集所有实现了ServletContextInitializer
接口的 Bean。Spring Boot 会在容器启动时通过
ServletWebServerApplicationContext
的onRefresh()
方法。在
onRefresh()
方法中,ServletWebServerApplicationContext
会调用createWebServer()
方法初始化嵌入式 Servlet 容器。最后会通过
new ServletContextInitializerBeans()
的方式,将所有实现了ServletContextInitializer
接口的 Bean保存到集合里(DispatcherServletRegistrationBean
)。最后遍历集合。循环调用实现类覆写的
onStartup
方法,对ServletContext
进行配置。最后添加到web容器中。
8.ServletContextInitializer区别
这里的ServletContextInitializer
不是指前面在讲SpringMVC中的ServletContextInitializer。不要混淆。
- Springboot中的
ServletContextInitializer,
为Springboot自己的包,由Spring自己管理。
1 |
|
- SpringMVC中的
ServletContextInitializer
,为javax.servlet的包:由容器管理。
1 |
|
9.WebMvcProperties
WebMvcProperties
是 Spring Boot
提供的一个配置属性类,用于自定义 Spring MVC
的一些常见设置。它使得开发者可以通过配置文件(如
application.properties
或
application.yml
)方便地配置 Spring MVC
的行为,而不需要编写大量的 Java 配置代码。
webMvcProperties.getServlet().getPath()
在Spring Boot应用中,主要用于获取DispatcherServlet
的映射路径配置。具体来说,它返回了在Spring Boot的配置文件(如application.properties
或application.yml
)中配置的DispatcherServlet
路径。这个路径定义了应用程序中请求路径的前缀,DispatcherServlet
将处理匹配这个路径的请求。
9.1 主要作用
- 简化配置:
WebMvcProperties
提供了一种集中化和简化配置的方法,使得开发者可以通过简单的属性配置来控制 Spring MVC 的行为。 - 统一管理: 所有与 Spring MVC 相关的配置属性都集中在一个地方,便于管理和维护。
1 |
|
9.2主要配置选项
以下是 WebMvcProperties
提供的一些常见配置选项及其作用:
spring.mvc.servlet.path
: 配置DispatcherServlet
的路径映射。例如,设置为/api
时,所有请求都必须以/api
开头。1
spring.mvc.servlet.path=/api
spring.mvc.view.prefix
和spring.mvc.view.suffix
: 配置视图解析器的前缀和后缀。例如,将视图名解析为/WEB-INF/views/
目录下的 JSP 文件。1
2spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jspspring.mvc.format.date
,spring.mvc.format.time
,spring.mvc.format.date-time
: 配置日期、时间和日期时间格式。1
2
3spring.mvc.format.date=yyyy-MM-dd
spring.mvc.format.time=HH:mm:ss
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ssspring.mvc.static-path-pattern
: 配置静态资源的路径模式。例如,设置为/static/**
时,静态资源会被映射到/static
目录。1
spring.mvc.static-path-pattern=/static/**
spring.mvc.throw-exception-if-no-handler-found
: 是否抛出异常当没有找到处理器时,默认是false
。1
spring.mvc.throw-exception-if-no-handler-found=true
spring.mvc.async.request-timeout
: 配置异步请求的超时时间。1
spring.mvc.async.request-timeout=5000 # 单位为毫秒
9.3 示例
假设我们有如下配置文件:
1 |
|
上述配置可以通过 WebMvcProperties
类自动绑定并应用到
Spring MVC 中,简化了配置过程。
9.4 总结
WebMvcProperties
的作用是简化和集中管理 Spring MVC
的各种配置选项,使得开发者可以通过配置文件快速定制 Spring MVC
的行为,从而提高开发效率和可维护性。
10.ispatcherServlet映射路径
Spring Boot 可以不配置
spring.mvc.servlet.path
。默认情况下,如果不配置这个属性,Spring
Boot 会将 DispatcherServlet
映射到根路径
/
,这意味着应用程序将处理所有传入的请求。
1 |
|
在 Servlet 配置中,loadOnStartup
参数用于指定 Servlet
的加载和初始化时机。该参数可以设置为以下值:
10.1 值的类型
- 正整数:表示在服务器启动时加载 Servlet。值越小,优先级越高,越早加载。
- 零或负整数:表示在服务器启动时不加载 Servlet,而是第一次收到请求时才加载。
所以Spring boot中,Servlet加载和初始化的时机默认是第一次收到请求时才加载。
博客说明
文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,不用于任何的商业用途。如有侵权,请联系本人删除。谢谢!