Spring MVC Handler处理流程

组件

ServletWebRequest

包装servlet的request和response

public class ServletWebRequest extends ServletRequestAttributes implements NativeWebRequest {
	private final HttpServletRequest request;

	@Nullable
	private HttpServletResponse response;

	@Nullable
	private volatile HttpSession session;
}

WebDataBinderFactory

生成DataBinder实例的工厂,DataBinder将request请求的参数绑定到java Bean对象

public interface WebDataBinderFactory {
	WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName)
			throws Exception;
}

ModelFactory

在真实处理器调用前初始化Model(数据模型Map),在调用结束后更新Model值。

public final class ModelFactory {
	private final List<ModelMethod> modelMethods = new ArrayList<>();
	// 请求数据绑定工厂
	private final WebDataBinderFactory dataBinderFactory;
	// session属性处理
	private final SessionAttributesHandler sessionAttributesHandler;
}
// 内部类
private static class ModelMethod {
	// 
	private final InvocableHandlerMethod handlerMethod;

	private final Set<String> dependencies = new HashSet<>();
}	

InvocableHandlerMethod

继承HandlerMethod,提供参数解析器和参数名寻找

public class InvocableHandlerMethod extends HandlerMethod {
	// 请求数据绑定工厂
	private WebDataBinderFactory dataBinderFactory;
	// 方法参数解析
	private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
	// 参数名寻找,生成NamedValueInfo时使用
	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
}

ServletInvocableHandlerMethod

继承InvocableHandlerMethod,在其基础上增加返回值处理器, 在方法级别支持@ResponseStatus注解。

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
}

ModelAndViewContainer

记录模型和视图的信息,持有一个默认的模型,当发生重定向时使用redirectModel代替默认模型记录数据。

public class ModelAndViewContainer {
	private boolean ignoreDefaultModelOnRedirect = false;
	@Nullable
	private Object view;
	private final ModelMap defaultModel = new BindingAwareModelMap();
	@Nullable
	private ModelMap redirectModel;
	// 为true返回重定向模型
	private boolean redirectModelScenario = false;
	@Nullable
	private HttpStatus status;
	// 请求是否处理完成
	private boolean requestHandled = false;
}	

RequestMappingHandlerAdapter

@RequestMapping注解使用的适配器

// 将属性存入Session中
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
// @SessionAttributes注解的处理,类+@SessionAttributes处理器
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);
// 实际处理类缓存的@ModelAttribute
private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
// 消息转换器 @RequestBody @ResponseBody 使用
private List<HttpMessageConverter<?>> messageConverters;

SessionAttributesHandler

@SessionAttributes注解的处理器,@SessionAttributes将指定的Model中的键值对添加至session中

public class SessionAttributesHandler {
	private final Set<String> attributeNames = new HashSet<>();
	private final Set<Class<?>> attributeTypes = new HashSet<>();
	private final Set<String> knownAttributeNames = Collections.newSetFromMap(new ConcurrentHashMap<>(4));
	private final SessionAttributeStore sessionAttributeStore;
}	

Handler处理流程

  1. DispatcherServlet中调用ha.handle(processedRequest, response, mappedHandler.getHandler());调用适配器处理请求,这里分析常用的RequestMappingHandlerAdapter。首先进入AbstractHandlerMethodAdapter的handle方法
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
	return handleInternal(request, response, (HandlerMethod) handler);
}
  1. 调用RequestMappingHandlerAdapter的handleInternal方法,首先检查是否支持给定请求,判断是否要求session同步,调用invokeHandlerMethod方法
protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ModelAndView mav;
	// 检查是否支持给定的请求
	checkRequest(request);

	// 如果要求在Session上同步
	if (this.synchronizeOnSession) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			Object mutex = WebUtils.getSessionMutex(session);
			synchronized (mutex) {
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No HttpSession available -> no mutex necessary
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}
	}
	else {
		// 通过反射调用真实处理器
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}
	// 如果不包含Cache-Control
	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		}
		else {
			prepareResponse(response);
		}
	}

	return mav;
}
  1. RequestMappingHandlerAdapter的invokeHandlerMethod方法调用,生成ServletInvocableHandlerMethod来调用处理器的方法,首先将request和response包装为ServletWebRequest,然后初始化两个工厂分别处理@InitBinder和@ModelAttribute注解。通过handlerMethod创建一个ServletInvocableHandlerMethod,为其设置参数和返回值解析器,创建MAV容器,反射调用方法,获得返回值。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
	// 用ServletWebRequest来包装request和response
	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
		// 用于从web请求参数到JavaBean对象的数据绑定,处理@InitBinder
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		// 协助在控制器方法调用之前初始化model,处理完成后更新model,处理@ModelAttribute
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		
		// 通过handlerMethod创建一个ServletInvocableHandlerMethod来反射执行
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
		if (this.argumentResolvers != null) {
			// 设置参数解析器
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		if (this.returnValueHandlers != null) {
			// 设置返回值解析器
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
		invocableMethod.setDataBinderFactory(binderFactory);
		// 用于解析方法和构造器的参数名
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		// MAV容器,关联视图和数据模型
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		// 为默认model设置数据
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		modelFactory.initModel(webRequest, mavContainer, invocableMethod);
		mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
		// 异步处理
		AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
		asyncWebRequest.setTimeout(this.asyncRequestTimeout);

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.setTaskExecutor(this.taskExecutor);
		asyncManager.setAsyncWebRequest(asyncWebRequest);
		asyncManager.registerCallableInterceptors(this.callableInterceptors);
		asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

		if (asyncManager.hasConcurrentResult()) {
			Object result = asyncManager.getConcurrentResult();
			mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
			asyncManager.clearConcurrentResult();
			invocableMethod = invocableMethod.wrapConcurrentResult(result);
		}
		// 反射调用处理器方法
		invocableMethod.invokeAndHandle(webRequest, mavContainer);
		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}
		// 获得处理器返回
		return getModelAndView(mavContainer, modelFactory, webRequest);
	}
	finally {
		webRequest.requestCompleted();
	}
}
  1. 调用ServletInvocableHandlerMethod的invokeAndHandle,对返回值进行判断,如果返回值为null或者实际处理器设置了响应码直接返回,否则调用返回值处理器来处理返回值。
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	// 设置响应状态
	setResponseStatus(webRequest);
	// 处理器已经完全处理了请求无MAV返回,或者响应码被设置了
	if (returnValue == null) {
		if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
			disableContentCachingIfNecessary(webRequest);
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	else if (StringUtils.hasText(getResponseStatusReason())) {
		mavContainer.setRequestHandled(true);
		return;
	}
	// 处理器处理完成后有返回且状态码未被修改
	mavContainer.setRequestHandled(false);
	try {
		// 调用返回值解析器处理返回值
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	···异常处理
}
  1. 调用InvocableHandlerMethod的invokeForRequest解析方法的传入参数
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
	// 参数解析
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	return doInvoke(args);
}
  1. 调用InvocableHandlerMethod的doInvoke方法,就是调用bridgedMethod的invoke反射方法来执行
protected Object doInvoke(Object... args) throws Exception {
	// 设置方法绕过检查
	ReflectionUtils.makeAccessible(getBridgedMethod());
	try {
		// 反射调用处理器方法
		return getBridgedMethod().invoke(getBean(), args);
	}
	····抛出异常
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值