SpringMVC执行流程简单分析

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 {
			* ModelAndViewModelView的功能
   			* 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);
				}
			}
		}
	}

这是
在这里插入图片描述

  1. WelcomePageHandlerMapping主要是处理欢迎页
  2. BeanNameUrlHandlerMapping则主要用于基于bean名称的传统映射方式,通常不适用于现代基于注解的控制器。 很少用到
  3. RouterFunctionMapping的作用是根据HTTP请求的路径、方法等信息,选择合适的处理函数来处理请求。很少用到
  4. 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请求。
  5. 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 已经被集成到了框架中,用于处理请求到控制器方法的映射。

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值