spring boot DispatcherServlet(三)handler执行

本文深入探讨了Spring Boot DispatcherServlet中handler的执行过程,包括handle方法、参数解析与执行、@RequestBody处理以及结果转换的详细步骤。文章剖析了HandlerAdapter如何调用handleInternal方法,进而触发handler方法的执行,解析请求参数,使用HandlerMethodArgumentResolverComposite进行转换,并通过RequestResponseBodyMethodProcessor将请求体转换为Java对象。最后,文章还介绍了结果转换的流程,涉及HandlerMethodReturnValueHandler的使用。
摘要由CSDN通过智能技术生成

handler 执行

之前的文章介绍到,当根据请求找到对应的handler之后,会根据这个handler找到对应的HandlerAdapter,解析来会调用handle方法来处理请求

// DispatcherServlet.java
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

handle

接下来看下HandlerAdapter是如何执行的
当调用handle时,主要会调用handleInternal方法

// RequestMappingHandlerAdapter.java
protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   

	ModelAndView mav;
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
	// 判断是否设置了synchronizeOnSession
	// 如果设置了,那么对于同一个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 {
   
		// No synchronization on session demanded at all...
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}

	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
   
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
   
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		}
		else {
   
			prepareResponse(response);
		}
	}

	return mav;
}

接下来看下invokeHandlerMethod
handler处理请求返回ModelAndView就是在这个地方进行的

// RequestMappingHandlerAdapter.java
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   

	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
   
		// WebDataBinder的工厂, WebDataBinder用来将web请求中的参数绑定到java对象上
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
		// 如果指定了HandlerMethodArgumentResolverComposite,那么设置到invocableMethod上
		if (this.argumentResolvers != null) {
   
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		// 如果指定了HandlerMethodReturnValueHandlerComposite,那么设置到invocableMethod上
		if (this.returnValueHandlers != null) {
   
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
		invocableMethod.setDataBinderFactory(binderFactory);
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		// 这里会将通过使用@SessionAttributes注解指定的session属性,设置到model中
		// 另外会执行@ModelAttributes注解的方法,在真正执行处理逻辑之前,将一些属性添加到model中
		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();
			LogFormatUtils.traceDebug(logger, traceOn -> {
   
				String formatted = LogFormatUtils.formatValue(result, !traceOn);
				return "Resume with async result [" + formatted + "]";
			});
			invocableMethod = invocableMethod.wrapConcurrentResult(result);
		}

		// 执行处理逻辑
		invocableMethod.invokeAndHandle(webRequest, mavContainer);
		if (asyncManager.isConcurrentHandlingStarted()) {
   
			return null;
		}
		
		// 获取ModelAndView
		return getModelAndView(mavContainer, modelFactory, webRequest);
	}
	finally {
   
		webRequest.requestCompleted();
	}
}

getDataBinderFactory

// RequestMappingHandlerAdapter.java
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
   
	// 返回handler的类型
	Class<?> handlerType = handlerMethod.getBeanType();
	// 获取当前handler可以使用的属性编辑器,包括全局的和当前handler自有的
	// @InitBinder用来为当前handler指定使用的属性编辑器,即如何将请求中的参数转换为java对象
	Set<Method> methods = this.initBinderCache.get(handlerType);
	if (methods == null) {
   
		methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
		this.initBinderCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
	// Global methods first
	// 首先会获取全局的InitBinder,即在使用了@ControllerAdvice注解的类中使用了@InitBinder注解的方法,将这些InitBinder添加到initBinderMethods集合中
	this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
   
		// 判断指定的ControllerAdvice是否能够作用到当前类
		// 通过@ControllerAdvice注解的basePackage basePackageClass assignableType annontation等属性来判断
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
   
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
   
				initBinderMethods.add(createInitBinderMethod(bean, method));
			}
		}
	});
	// 处理当前handler中使用了@InitBinder注解的方法
	for (Method method : methods) {
   
		Object bean = handlerMethod.getBean();
		initBinderMethods.add(createInitBinderMethod(bean, method));
	}
	return createDataBinderFactory(initBinderMethods);
}

接着看下createInitBinderMethod方法,该方法用来对当前bean和待执行的方法创建一个InvocableHanderMethod

// RequestMappingHandlerAdapter.java
private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
   
	InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
	if (this.initBinderArgumentResolvers != null) {
   
		binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
	}
	binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
	binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
	return binderMethod;
}

getModelFactory

和上面相同的方法来处理@ModelAttribute注解

// RequestMappingHandlerAdapter.java
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
   
	SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
	Class<?> handlerType = handlerMethod.getBeanType();
	Set<Method> methods = this.modelAttributeCache.get(handlerType);
	if (methods == null) {
   
		methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
		this.modelAttributeCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
	// Global methods first
	this
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值