日常提交

This commit is contained in:
wu xiangkai
2022-11-17 18:05:52 +08:00
parent e38a9a9333
commit c32dd7ead5

View File

@@ -3,3 +3,58 @@
SpringMVC是一款基于Servlet API的web框架并基于前端控制器的模式被设计。前端控制器有一个中央的控制器DispatcherServlet通过一个共享的算法来集中分发请求请求实际是通过可配置的委托组件@Controller类)来处理的。 SpringMVC是一款基于Servlet API的web框架并基于前端控制器的模式被设计。前端控制器有一个中央的控制器DispatcherServlet通过一个共享的算法来集中分发请求请求实际是通过可配置的委托组件@Controller类)来处理的。
> Spring Boot遵循不同的初始化流程。相较于hooking到servlet容器的生命周期中Spring Boot使用Spring配置来启动其自身和内置servlet容器。filter和servlet声明在在spring配置中被找到并且被注入到容器中。 > Spring Boot遵循不同的初始化流程。相较于hooking到servlet容器的生命周期中Spring Boot使用Spring配置来启动其自身和内置servlet容器。filter和servlet声明在在spring配置中被找到并且被注入到容器中。
## DispatcherServlet
### Context层次结构
DispatcherServlet需要一个WebApplicationContextApplicationContext的拓展类Spirng容器来进行配置。WebApplicationContext拥有一个指向ServletContext和与ServletContext关联Servlet的链接。
**同样的也可以通过ServeltContext来获取关联的ApplicationContext可以通过RequestContextUtils中的静态方法来获取ServletContext关联的ApplicationContext。**
#### WebApplicationContext的继承关系
对大多数应用含有一个WebApplicationContext就足够了。也可以存在一个Root WebApplicationContext在多个DispatcherServlet实例之间共享同时DispatcherServlet实例也含有自己的WebApplicationContext。
通常被共享的root WebApplicationContext含有repository或service的bean对象这些bean对象可以被多个DispatcherServlet实例的子WebApplicationContext共享。同时子WebApplicationContext在继承root WebApplicationContext中bean对象的同时还能对root WebApplicationContext中的bean对象进行覆盖。
> #### WebApplicationContext继承机制
> 只有当Servlet私有的子WebApplicationContext中没有找到bean对象时才会从root WebApplicationContext中查找bean对象此行为即是对root WebApplicationContext的继承
### Spring MVC中特殊的bean类型
DispatcherServlet将处理请求和渲染返回的工作委托给特定的bean对象。Spring MVC中核心的bean类型如下。
#### HandlerMapping
将请求映射到handler和一系列用于pre/post处理的拦截器。
#### HandlerAdapter
HandlerAdapter主要是用于帮助DispatcherServlet调用request请求映射到的handler对象。
通常在调用含有注解的controller时需要对注解进行解析而HandlerAdapter可以向DispatcherServlet隐藏这些细节DispatcherServlet不必关心handler是如何被调用的。
#### HandlerExceptionResolver
解析异常的策略可能将异常映射到某个handler或是映射到html error页面。
#### ViewResolver
将handler返回的基于字符串的view名称映射到一个特定的view并通过view来渲染返回的响应。
### Web MVC Config
在应用中可以定义上小节中包含的特殊类型bean对象。DispatcherServlet会检查WebApplicationContext中存在的特殊类型bean对象如果某特殊类型的bean对象在容器中不存在那么会存在一个回滚机制使用DispatcherServlet.properties中默认的bean类型来创造bean对象例如DispatcherServlet.properties中指定的默认HandlerMapping类型是 org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.)。
### Servlet Config
在Servlet环境中可以选择通过java代码的方式或者web.xml的方式来配置servlet容器。
配置Servlet的详细方式参照Spring MVC文档。
### 请求处理过程
DispatcherServlet按照如下方式来处理Http请求
1. 首先会找到WebApplicationContext并且将其绑定到请求中此后controller和其他元素在请求处理的过程中可以使用该WebApplicationContext。**默认情况下WebApplicationContext被绑定到DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中**
2. locale resolver被绑定到请求中在请求处理过程中可以被其他元素使用
3. theme resolver被绑定到请求中在请求处理过程中可以被其他元素使用
4. 如果指定了multipart file resolver请求会被检查是否存在multipart。如果multipart被找到该请求会被包装在一个MultipartHttpServletRequest中并等待对其进行进一步的处理
5. 一个合适的handler将会被找到并且和该handler相关联的execution chainpre/post/Controller)会被执行返回一个model用于渲染。
6. 如果model被返回那么返回的model会被渲染。如果model没有返回那么没有view会被渲染。
在WebApplicationContext中声明的HandlerExceptionResolver会用于解析处理请求中抛出的异常。
### 路径匹配
Servlet API将完整的请求路径暴露为requestURI并且进一步划分requestURI为如下部分contextPathservletPathpathInfo。
> #### contextPath, servletPath, pathInfo区别
> - contextPathcontextPath为应用被访问的路径是整个应用的根路径。默认情况下SpringBoot的contextPath为"/"。可以通过server.servlet.context-path="/demo"来改变应用的根路径。
> - servletPathservletPath代表main DispatcherServlet的路径。默认情况下servletPath的值仍为"/"。可以通过spring.mvc.servlet.path来自定义该值。
### Interception
所有HandlerMapping的实现类都支持handler interceptor当想要为特定请求执行指定逻辑时会相当有用。拦截器必须要实现HandlerInterceptor该接口提供了三个方法
- preHandle在实际handler处理之前
- postHandle在 实际handler处理之后
- afterCompletion在请求完成之后
#### preHandle
preHandle方法会返回一个boolean值可以通过指定该方法的返回值来阻止执行链继续执行。当preHandle的返回值是true时后续执行链会继续执行当返回值是false时DispatcherServlet会假设该拦截器本身已经处理了请求并不会继续执行execution chain中的其他拦截器和实际handler。
#### postHandle
对于@ResponseBody或返回值为ResponseEntity的方法postHandle不起作用这些方法在HandlerAdapter中已经写入且提交了返回响应时间位于postHandle之前。到postHandle方法执行时已经无法再对响应做任何修改如添加header也不再被允许。对于这些场景可以**实现ResponseBodyAdvice或者声明一个ControllerAdvice**。
#### afterCompletion
调用时机位于DispaterServlet渲染view之后。