SpringMVC 处理请求原理


前言


学习 springmvc 处理请求流程前,有一些前置知识,在我的另一篇文章 《SpringMVC 启动原理》中,建议先阅读完,在来看本篇。

springmvc 处理请求流程 - 大白话描述


整理的 springmvc 处理请求的流程图:

springmvc处理请求流程图

图中步骤详解:

  1. Tomcat 会监听请求
  2. 当请求到达后,Tomcat 会调用 Servlet 的 service 方法,也就是 DispatcherServlet 的 service 方法
  3. service 方法最终会调用 DispatcherServlet 中的 doDispatch 方法。请求处理的核心流程都在这个方法里
  4. 在 doDispatch 方法中,首先会根据 请求的路径,在 handlerMappings 中查找对应的 Handler。一般研究的都是 RequestMappingHandlerMapping,所以后续都是基于 RequestMappingHandlerMapping 介绍。
  5. 找到 Handler 后,再查找和 RequestMappingHandlerMapping 相对应的 HandlerAdapter,也就是RequestMappingHandlerAdapter。
  6. 执行拦截器的前置方法 preHandle,如果验证通过,就继续执行。
  7. 调用 RequestMappingHandlerAdapter 的 handle 方法。
  8. 用 RequestMappingHandlerAdapter 中的 参数解析器,来构建 Handler 的参数。
  9. 把构建的参数传入 Handler,并执行 Handler,也就是进行真正的业务调用,调我们写的方法。
  10. Handler 执行完毕后,用 RequestMappingHandlerAdapter 中的 返回值解析器 来处理返回结果。这里会有两种常见的分支:
    • 通过 @ResponseBody 修饰时:
      这种情况对应的 返回值解析器是 RequestResponseBodyMethodProcessor,返回值解析器 会调用 messageConvert 来处理返回值,@ResponseBody 修饰的返回值是对象时,对应的 messageConvert 就是MappingJackson2HttpMessageConverter,这个 messageConvert 会将返回值对象转换成 Json 字符串。
    • 返回 ModelAndView 的时:
      这种情况对应的 返回值解析器是 ModelAndViewMethodReturnValueHandler,返回值解析器 中会设置一个 viewName
  11. 执行拦截器的后置方法 postHandle
  12. 最后会根据 是否设置了 viewName 来决定向客户端返回的内容。
    • 无 viewName 时,会直接把 Json 字符串返回给客户端。
    • 有 viewName 时,会继续调用 RequestMappingHandlerAdapter 中的视图处理器来渲染页面,最后把页面返回给客户端。

springmvc 处理请求流程 - 关键源码

1. 对应图中的紫色部分


// 请求最终会转发到这里
public class DispatcherServlet {
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 根据请求路径找到对应的 Handler
		mappedHandler = getHandler(processedRequest)
		// 找到与 HandlerMapping 对应的 HandlerAdapter
		HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
		// 拦截器前处理
		if (!mappedHandler.applyPreHandle(processedRequest, response)) {
			return;
		}
		// 调用 Adapter 的handle 方法
		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	}
}

2. 对应图中的浅蓝色部分


public class RequestMappingHandlerAdapter {
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		// 执行业务逻辑
		invocableMethod.invokeAndHandle(webRequest, mavContainer);
	}
}
public class ServletInvocableHandlerMethod {
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 执行业务逻辑
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		// 调用返回值解析器
		this.returnValueHandlers.handleReturnValue(
						returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
}
public class InvocableHandlerMethod {
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 调用参数解析器
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		// 将参数传入 handler,并真正的执行业务逻辑
		Object returnValue = doInvoke(args);
	}
}


3. 对应图中的绿色部分


// @ResponseBody 修饰时的返回值处理器
public class RequestResponseBodyMethodProcessor {
	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
		// 通过 messageConvert 处理返回值
		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
	}
	protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
			ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
			// 找到对应的 messageConvert
			for (HttpMessageConverter converter : this.messageConverters) {
			}
	}
}

4. 对应图中的黄色部分


// 返回值是 ModelAndView 时的 返回值处理器
public class ModelAndViewMethodReturnValueHandler {
	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
		// 设置视图名字
		mavContainer.setViewName(viewName);
	}
}

5.对应图中的粉色部分


public class DispatcherServlet {
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// 拦截器的后置处理器
	mappedHandler.applyPostHandle(processedRequest, response, mv);
	// 判断 handler 的返回值是否是视图
	processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {
		// 当返回值不是视图时这个 mv 是 null
		if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);
		}
	}
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (viewName != null) {
			// 调用视图解析器
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值