当请求来到,并找到正确的Controller以及HandlerAdapter以后。就该执行方法了。web
这里说的是 3.0版本以后的 RequestMappingAdapter 的解析执行过程。app
如下源码都是简化以后的。ide
首先,在DispatcherServlet部分源码以下ui
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // 找controller mappedHandler = getHandler(processedRequest); // 找HandlerAdaper HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // HandlerAdaper执行handle方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } }
最后的handle方法,是调用到了RequestMappingAdapter的handleInternal()方法。this
RequestMappingAdapter源码以下spa
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { mav = invokeHandlerMethod(request, response, handlerMethod); return mav; }
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { try { // 每一个请求过来的时候,都会新建一个ServletInvocableHandlerMethod 对象 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); // 给ServletInvocableHandlerMethod 对象设置方法参数解析器、方法返回值解析器 等 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); // 交给 ServletInvocableHandlerMethod 来处理请求了 invocableMethod.invokeAndHandle(webRequest, mavContainer); }
在 ServletInvocableHandlerMethod 类中,源码以下debug
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 处理请求,invokeForRequest方法是父类InvocableHandlerMethod 的,父类主要处理请求 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); try { // 处理返回值 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } }
InvocableHandlerMethod 类的源码 以下对象
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 获取方法的参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); // 内部经过反射,调用controller 中的方法。 Object returnValue = doInvoke(args); return returnValue; }
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); args[i] = resolveProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } // 这个参数解析器是刚刚RequestMappingHandlerAdapter给注入的,是 HandlerMethodArgumentResolverComposite // 类型,它实现了HandlerMethodArgumentResolver接口,是个HandlerMethodArgumentResolver组合(集合) if (this.argumentResolvers.supportsParameter(parameter)) { try { // 解析参数,获得参数。 args[i] = this.argumentResolvers.resolveArgument( parameter, mavContainer, request, this.dataBinderFactory); continue; } } return args; }
HandlerMethodArgumentResolverComposite类的 supportsParameter具体实现以下,其实就是在它的属性里有个List<HandlerMethodArgumentResolver>,而后看这个list里面有没有supports的。接口
@Override public boolean supportsParameter(MethodParameter parameter) { return (getArgumentResolver(parameter) != null); }
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) { if (logger.isTraceEnabled()) { logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" + parameter.getGenericParameterType() + "]"); } // 这个就是遍历 List<HandlerMethodArgumentResolver> 里面的参数解析器,看有没有suppotrs的。 if (methodArgumentResolver.supportsParameter(parameter)) { result = methodArgumentResolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }
参数的解析大致流程就是上面的代码了,补一下总体的结构。更加清晰一些get
RequestMappingHandlerAdapter的属性有以下(部分)
// 如下是 处理方法参数的解析器,第一个是须要咱们自定义,第二个是默认的 private List<HandlerMethodArgumentResolver> customArgumentResolvers; private HandlerMethodArgumentResolverComposite argumentResolvers; // 如下是 处理方法返回值的解析器,第一个是须要咱们自定义,第二个是默认的 private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
那么RequestMappingHandlerAdapter的 argumentResolvers 和 returnValueHandlers是哪里来的呢?
是Spring启动时注册RequestMappingHandlerAdapter的时候自动注入的。以下
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>(); // Annotation-based argument resolution resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ServletModelAttributeMethodProcessor(false)); resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); resolvers.add(new MapMethodProcessor()); resolvers.add(new ErrorsMethodArgumentResolver()); resolvers.add(new SessionStatusMethodArgumentResolver()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // Custom arguments if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers; }
而后执行handle方法的时候,RequestMappingHandlerAdapter 又把这两个属性给了
ServletInvocableHandlerMethod。而后ServletInvocableHandlerMethod利用解析器作各类处理。
ServletInvocableHandlerMethod 是主要处理 方法返回值的,它的父类是
InvocableHandlerMethod 是主要处理 方法参数的。 它的父类就是 HandlerMethod 了。
因此以上主要涉及的几个类,名字都比较长。不能混淆,都要知道它们各自是干吗的,本文比较粗略,内部仍是没有debug,我目前也就理解到这里了。