SpringMVC请求参数解析

客户端请求在handlerMapping中找到对应handler后,将会继续执行DispatchServlet的doPatch()方法。

首先是找到handler对应的适配器。

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
进入到getHandlerAdapter(mappedHandler.getHandler())方法中

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException(“No adapter for handler [” + handler +
“]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler”);
}
这里存在多个适配器,如图:

其中使用@RequestMaping注解修饰的控制器都将适配第一个适配器;而函数式方法将会使用第二个适配器。

跟踪请求,这里将会获得第一个适配器,判断也简单,如下:

public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
如果是HandlerMethod类型的处理器就采用这个适配器,而客户端请求正好对应的是HandlerMethod处理器。

找到适配器后,将会真正执行处理器逻辑。如下:

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
进入RequestMappingHandlerAdapter,执行适配器核心方法:

@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ModelAndView mav;
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
	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;
}

其核心代码为实际执行处理器方法:

mav = invokeHandlerMethod(request, response, handlerMethod);
同样,我们打开RequestMappingHandlerAdapter中的invokeHandlerMethod方法:

@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
        //通过处理器获得真正的执行方法及其参数列表
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        //给执行方法对象添加参数解析器
		if (this.argumentResolvers != null) {
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
        //给执行方法对象添加返回值处理器
		if (this.returnValueHandlers != null) {
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
        //处理器对象装配完成,执行控制器方法
	invocableMethod.invokeAndHandle(webRequest, mavContainer);
	if (asyncManager.isConcurrentHandlingStarted()) {
		return null;
	}

	return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
	webRequest.requestCompleted();
}

}

在这个关键方法中,首先执行请求对应的控制器逻辑,之后进行系列处理,根据返回值处理器处理返回值。

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object… providedArgs) throws Exception {
//执行控制器方法
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);

	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);
	Assert.state(this.returnValueHandlers != null, "No return value handlers");
	try {
        //处理返回值
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		if (logger.isTraceEnabled()) {
			logger.trace(formatErrorForReturnValue(returnValue), ex);
		}
		throw ex;
	}
}

以下给出部分参数解析器及返回值处理器截图:

参数解析器。对应每一个参数(路径变量、矩阵变量、获得请求头、请求域等)的获取方式

返回值处理器。ModelAndView、ResponseBody等。每个处理器处理不同类别的返回值类型。

接下来,真正进入到最终执行method方法invocableMethod.invokeAndHandle(webRequest, mavContainer);,这里是真是执行控制器中映射的方法。

以下为获得参数列表对应值的逻辑,参数获取完成后将会执行真正的控制器逻辑。

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object… providedArgs) throws Exception {
//通过参数解析器获取参数列表每一个参数的值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
return doInvoke(args);
}
进入解析逻辑,解析是对比每一个参数绑定的注解,如果注解一致将会使用对应的解析器将请求传递的参数值获取到。

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object… providedArgs) throws Exception {
//获得控制器参数列表,每一个参数包含其参数类型,参数次序、注解修饰(用于使用对应解析器)
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}

	Object[] args = new Object[parameters.length];
	for (int i = 0; i < parameters.length; i++) {
        //轮循获得参数
		MethodParameter parameter = parameters[i];
		parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
		args[i] = findProvidedArgument(parameter, providedArgs);
		if (args[i] != null) {
			continue;
		}
        //判断解析器是否支持当前参数的解析
		if (!this.resolvers.supportsParameter(parameter)) {
			throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
		}
		try {
            //获得参数值的核心方法
			args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		}
		catch (Exception ex) {
			// Leave stack trace for later, exception may actually be resolved and handled...
			if (logger.isDebugEnabled()) {
				String exMsg = ex.getMessage();
				if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
					logger.debug(formatArgumentError(parameter, exMsg));
				}
			}
			throw ex;
		}
	}
	return args;
}

查看解析器是否指出当前参数部分代码,可以了解到SpringMVC的缓存策略。

private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
//从缓存中获取当前参数的解析器
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
//缓存中不存在则将这个参数对应的解析器加到缓存中,提升后续相同请求响应速度。
if (result == null) {
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值