您的位置:首页 > 编程语言 > Java开发

【spring-mvc】spring-mvc中handlerMethod的执行

2016-02-17 18:14 483 查看

今天来聊聊spring-mvc是如何来执行Controller中的method的。

spring-mvc默认的HandlerAdapter是RequestMappingHandlerAdapter,

DispatcherServlet将处理逻辑交由HandlerAdapter,而HandlerAdapter,由交给ServletInvocableHandlerMethod来invokeAndHandle.

requestMappingMethod.invokeAndHandle(webRequest, mavContainer);


跟踪源代码

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) || hasResponseStatus() || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(this.responseReason)) {
mavContainer.setRequestHandled(true);
return;
}

mavContainer.setRequestHandled(false);
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}


主要是
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs)
整个执行过程都在这步代码中,那么到底是如何处理的。

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
StringBuilder sb = new StringBuilder("Invoking [");
sb.append(getBeanType().getSimpleName()).append(".");
sb.append(getMethod().getName()).append("] method with arguments ");
sb.append(Arrays.asList(args));
logger.trace(sb.toString());
}
Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
}
return returnValue;
}


我们知道利用反射来执行一个方法的时候,我们需要入参。那么
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
就是获取Controller的入参。也就是需要用到参数解析了,spring-mvc为我们提供了强大的数据绑定机制,

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//argumentResolvers是RequestMappingHandlerAdapter传过来的参数解析器。
//这里是循环遍历,查找能够解析该参数的
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
}
throw ex;
}
}
if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg);
}
}
return args;
}


下一步就是找到参数解析器来解析该参数了 。spring-mvc为我们提供了23种参数解析器。这里就不一一介绍了,

得到参数之后,然后调用
Object returnValue = doInvoke(args);
得到执行的返回结果。

this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);


下面的处理逻辑:如果是视图,就调用ViewResolver,render出jsp,如何是JSON。则用response写到应用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: