日常提交
This commit is contained in:
@@ -3,3 +3,58 @@
|
||||
SpringMVC是一款基于Servlet API的web框架,并基于前端控制器的模式被设计。前端控制器有一个中央的控制器(DispatcherServlet),通过一个共享的算法来集中分发请求,请求实际是通过可配置的委托组件(@Controller类)来处理的。
|
||||
> Spring Boot遵循不同的初始化流程。相较于hooking到servlet容器的生命周期中,Spring Boot使用Spring配置来启动其自身和内置servlet容器。filter和servlet声明在在spring配置中被找到并且被注入到容器中。
|
||||
|
||||
## DispatcherServlet
|
||||
### Context层次结构
|
||||
DispatcherServlet需要一个WebApplicationContext(ApplicationContext的拓展类,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 chain(pre/post/Controller)会被执行,返回一个model用于渲染。
|
||||
6. 如果model被返回,那么返回的model会被渲染。如果model没有返回,那么没有view会被渲染。
|
||||
|
||||
在WebApplicationContext中声明的HandlerExceptionResolver会用于解析处理请求中抛出的异常。
|
||||
### 路径匹配
|
||||
Servlet API将完整的请求路径暴露为requestURI,并且进一步划分requestURI为如下部分:contextPath,servletPath,pathInfo。
|
||||
> #### contextPath, servletPath, pathInfo区别
|
||||
> - contextPath:contextPath为应用被访问的路径,是整个应用的根路径。默认情况下,SpringBoot的contextPath为"/"。可以通过server.servlet.context-path="/demo"来改变应用的根路径。
|
||||
> - servletPath:servletPath代表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之后。
|
||||
|
||||
Reference in New Issue
Block a user