protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
* requst对象
HttpServletRequest processedRequest = request;
* 处理器执行链 里面有handler、interceptor、拦截器索引
* 责任链模式
HandlerExecutionChain mappedHandler = null;
*文件解析器是否需要 默认false
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
* ModelAndView有Model和View的功能
* Model主要用于向请求域共享数据
* View主要用于设置视图,实现页面跳转
ModelAndView mv = null;
Exception dispatchException = null;
try {
* 检查是否需要文件解析器 (具体自己点进去看)
* 其中判断方法就是startswithIgnoreCase
* 在Content-type中判断是不是以"multipart/"为前缀
* 如果是就会调用文件上传组件,不是就直接返回
* StandardMultipartHttpServletRequest这个类是具体实现,里面就是调用文件上传具体流程
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
* 它会遍历所有的 HandlerMapping 实现
* 直到找到一个匹配当前请求的处理器。
* 等然后封装到HandlerExecutionChain中
* 拦截器和handler都在这里面
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 处理器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
* 请求方法 如GET
String method = request.getMethod();
* 下面一段主要是检查缓存 不必理会
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
* 这里执行拦截器的 preHandle方法
* 里面有一个遍历过程 下次写
* preHandle方法如果return false就会结束 true继续执行
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
* 处理器适配器调用handler方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
* 这里执行拦截器的 postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
* 1.处理异常的方法
* 2.处理视图方法 render
* 3.调用拦截器的afterCompletion方法 triggerAfterCompletion
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
这是
- WelcomePageHandlerMapping主要是处理欢迎页
- BeanNameUrlHandlerMapping则主要用于基于bean名称的传统映射方式,通常不适用于现代基于注解的控制器。 很少用到
- RouterFunctionMapping的作用是根据HTTP请求的路径、方法等信息,选择合适的处理函数来处理请求。很少用到
- SimpleUrlHandlerMapping类,主要是对xml配置的handler的处理,我们常用注解方式@Controller它是Spring框架中的一个处理器映射器实现。这个类的主要功能是将URL路径映射到处理请求的bean上。
构造函数初始化一个LinkedHashMap来存储URL到处理器的映射。
setMappings方法允许通过Properties对象设置URL到处理器bean名称的映射。
setUrlMap方法允许直接设置URL到处理器bean或其名称的映射。
getUrlMap方法提供对URL映射的访问,并允许添加或覆盖特定条目。
initApplicationContext方法在应用上下文初始化时注册所有处理器。
registerHandlers方法注册URL映射中的所有处理器,并处理URL和处理器bean名称的格式化。
简而言之,SimpleUrlHandlerMapping负责根据配置的URL映射选择合适的处理器bean来处理HTTP请求。- RequestMappingHandlerMapping最常用处理基于注解的handler 继承自 RequestMappingInfoHandlerMapping,是Spring MVC框架中的核心组件之一,主要用于处理HTTP请求与控制器方法之间的映射关系。具体功能如下:
请求映射:根据配置的注解(如 @RequestMapping, @GetMapping, @PostMapping 等),将HTTP请求映射到相应的控制器方法上。
参数解析:解析请求路径中的变量部分,并将其绑定到控制器方法的参数上。
方法选择:支持多种HTTP方法(如GET、POST等),根据请求类型选择合适的方法处理请求。
优先级设置:可以通过配置设置不同映射器的优先级,以控制处理请求时的顺序。
简而言之,它负责在Spring MVC框架中实现从HTTP请求到具体处理方法的映射逻辑。
例子:
@Controller
public class MyController {
@PostMapping(value = "/users/{userId}", params = {"lang=en"}, headers = "Accept=application/json")
public String createUser(@PathVariable Long userId, @RequestParam String lang, @RequestBody User user) {
// 处理逻辑
return "success";
}
}
构建 RequestMappingInfo 当 Spring 启动时,RequestMappingHandlerMapping 会扫描带有
@RequestMapping 注解的方法,并为每个方法创建一个 RequestMappingInfo 对象。
对于上述例子中的控制器方法,RequestMappingInfo 可以这样构建:
// 构建 RequestMappingInfo 对象
RequestMappingInfo requestMappingInfo = new RequestMappingInfo(
// name: 名称为空
null,
// pathPatternsCondition: 路径模式
PathPatternsRequestCondition.forPattern("/users/{userId}"),
// patternsCondition: 模式条件
PatternsRequestCondition.forPatterns("/users/{userId}"),
// methodsCondition: 请求方法
RequestMethodsRequestCondition.forMethods(HttpMethod.POST),
// paramsCondition: 参数条件
ParamsRequestCondition.forParams(Map.of("lang", new String[]{"en"})),
// headersCondition: 头部条件 consumesCondition: 可消费类型
HeadersRequestCondition.create(Map.of("Accept", new String[]{"application/json"})), ConsumesRequestCondition.forConsumeTypes(MediaType.APPLICATION_JSON),
ProducesRequestCondition.forProduceTypes(MediaType.APPLICATION_JSON), // producesCondition: 可生产类型
// customConditionHolder: 自定义条件
EMPTY_CUSTOM,
// options: 构建配置
BuilderConfiguration.DEFAULT
);
请求映射过程
当一个 HTTP 请求到达时,例如 POST /users/123?lang=en 并且请求头包含 Accept: application/json,RequestMappingHandlerMapping 将会检查该请求是否与任何已注册的 RequestMappingInfo 匹配。
路径匹配:/users/123 与 /users/{userId} 匹配。
方法匹配:POST 方法与 @PostMapping 匹配。
参数匹配:请求参数包含 lang=en,与 params = {“lang=en”} 匹配。
头部匹配:请求头包含 Accept: application/json,与 headers = “Accept=application/json” 匹配。
可消费类型匹配:请求体的 MIME 类型为 application/json,与 ConsumesRequestCondition 匹配。
可生产类型匹配:控制器可以返回 application/json 类型的内容,与 ProducesRequestCondition 匹配。
如果所有条件都匹配,则 RequestMappingHandlerMapping 会将请求映射到 MyController 的 createUser 方法上。
这就是 RequestMappingHandlerMapping 使用 RequestMappingInfo 进行请求映射的过程。
处理器适配器
AI解释
和前面的处理器映射器相似,这里有4个主要的是RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 是 Spring MVC 框架中的一个核心组件,它负责处理 HTTP
请求与控制器方法之间的映射关系。具体来说,它实现了将 HTTP
请求转发给合适的控制器方法的功能,并处理方法参数绑定、返回值处理等工作。以下是关于 RequestMappingHandlerAdapter
的几个关键点: 作用: 处理 HTTP 请求到控制器方法的映射。 解析请求数据并将其绑定到控制器方法的参数上。 负责调用控制器方法。 处理控制器方法的返回值。
工作流程: 当 HTTP 请求到达时,DispatcherServlet 将请求委托RequestMappingHandlerMapping 来找到合适的处理器对象(通常是控制器类的方法)。
RequestMappingHandlerMapping 根据配置的 @RequestMapping 注解等信息找到合适的处理器,并返回一个
HandlerExecutionChain 对象,其中包含了处理器对象和拦截器列表。 DispatcherServlet 再将
HandlerExecutionChain 交给 RequestMappingHandlerAdapter 来执行。
RequestMappingHandlerAdapter 负责解析请求数据,并将其绑定到处理器方法的参数上。
执行控制器方法,并处理其返回值。 配置: 在 Spring MVC 中,通常不需要直接配置
RequestMappingHandlerAdapter,因为它会自动注册。 可以通过自定义 WebMvcConfigurer 或者扩展
WebMvcConfigurationSupport 类来自定义或覆盖默认的行为。 在 Java 开发环境中,如果你正在使用 Spring
MVC,那么 RequestMappingHandlerAdapter 已经被集成到了框架中,用于处理请求到控制器方法的映射。