private String determineHeaderExpression(
     Header headerAnnotation, MethodParameter methodParameter) {
   methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER);
   String headerName = null;
   String relativeExpression = "";
   String valueAttribute = headerAnnotation.value();
   if (!StringUtils.hasText(valueAttribute)) {
     headerName = methodParameter.getParameterName();
   } else if (valueAttribute.indexOf('.') != -1) {
     String tokens[] = valueAttribute.split("\\.", 2);
     headerName = tokens[0];
     if (StringUtils.hasText(tokens[1])) {
       relativeExpression = "." + tokens[1];
     }
   } else {
     headerName = valueAttribute;
   }
   Assert.notNull(
       headerName,
       "Cannot determine header name. Possible reasons: -debug is "
           + "disabled or header name is not explicitly provided via @Header annotation.");
   String headerRetrievalExpression = "headers['" + headerName + "']";
   String fullHeaderExpression = headerRetrievalExpression + relativeExpression;
   String fallbackExpression =
       (headerAnnotation.required())
           ? "T(org.springframework.util.Assert).isTrue(false, 'required header not available:  "
               + headerName
               + "')"
           : "null";
   return headerRetrievalExpression
       + " != null ? "
       + fullHeaderExpression
       + " : "
       + fallbackExpression;
 }
  private UriComponents applyContributers(
      UriComponentsBuilder builder,
      Method method,
      Object[] argumentValues,
      Map<String, Object> uriVars) {

    if (this.contributors.isEmpty()) {
      return builder.buildAndExpand(uriVars);
    }

    int paramCount = method.getParameters().length;
    int argCount = argumentValues.length;

    Assert.isTrue(
        paramCount == argCount,
        "Number of method parameters "
            + paramCount
            + " does not match number of argument values "
            + argCount);

    for (int i = 0; i < paramCount; i++) {
      MethodParameter param = new MethodParameter(method, i);
      param.initParameterNameDiscovery(parameterNameDiscoverer);
      for (UriComponentsContributor c : this.contributors) {
        if (c.supportsParameter(param)) {
          c.contributeMethodArgument(
              param, argumentValues[i], builder, uriVars, this.conversionService);
          break;
        }
      }
    }

    return builder.buildAndExpand(uriVars);
  }
 /**
  * Gets parameter name of this action input parameter.
  *
  * @return name
  */
 public String getParameterName() {
   String ret;
   String parameterName = methodParameter.getParameterName();
   if (parameterName == null) {
     methodParameter.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
     ret = methodParameter.getParameterName();
   } else {
     ret = parameterName;
   }
   return ret;
 }
  /**
   * Creates a new instance of {@link Parameters}.
   *
   * @param method
   */
  public Parameters(Method method) {

    Assert.notNull(method);

    this.parameters = new ArrayList<Parameter>();

    List<Class<?>> types = Arrays.asList(method.getParameterTypes());

    for (int i = 0; i < types.size(); i++) {
      MethodParameter parameter = new MethodParameter(method, i);
      parameter.initParameterNameDiscovery(discoverer);
      parameters.add(createParameter(parameter));
    }

    this.pageableIndex = types.indexOf(Pageable.class);
    this.sortIndex = types.indexOf(Sort.class);

    assertEitherAllParamAnnotatedOrNone();
  }
 private String asString(HandlerMethod handlerMethod) {
   StringBuilder sb = new StringBuilder();
   sb.append("\nController:\n").append(handlerMethod.getBeanType().getSimpleName());
   sb.append("\nMethod:\n");
   sb.append(handlerMethod.getMethod().getReturnType().getSimpleName()).append(" ");
   sb.append(handlerMethod.getMethod().getName()).append("(");
   for (MethodParameter param : handlerMethod.getMethodParameters()) {
     param.initParameterNameDiscovery(this.parameterNameDiscoverer);
     for (Annotation annotation : param.getParameterAnnotations()) {
       sb.append(annotation).append(" ");
     }
     sb.append(param.getParameterType().getSimpleName()).append(" ");
     sb.append(param.getParameterName());
     if (param.getParameterIndex() < handlerMethod.getMethodParameters().length - 1) {
       sb.append(" ");
     }
   }
   sb.append(")\n");
   return sb.toString();
 }
  private static UriComponents applyContributors(
      UriComponentsBuilder builder, Method method, Object... args) {
    CompositeUriComponentsContributor contributor = getConfiguredUriComponentsContributor();
    if (contributor == null) {
      logger.debug("Using default CompositeUriComponentsContributor");
      contributor = defaultUriComponentsContributor;
    }

    int paramCount = method.getParameterTypes().length;
    int argCount = args.length;
    if (paramCount != argCount) {
      throw new IllegalArgumentException(
          "Number of method parameters "
              + paramCount
              + " does not match number of argument values "
              + argCount);
    }

    final Map<String, Object> uriVars = new HashMap<String, Object>();
    for (int i = 0; i < paramCount; i++) {
      MethodParameter param = new MethodParameter(method, i);
      param.initParameterNameDiscovery(parameterNameDiscoverer);
      contributor.contributeMethodArgument(param, args[i], builder, uriVars);
    }

    // We may not have all URI var values, expand only what we have
    return builder
        .build()
        .expand(
            new UriComponents.UriTemplateVariables() {
              @Override
              public Object getValue(String name) {
                return uriVars.containsKey(name)
                    ? uriVars.get(name)
                    : UriComponents.UriTemplateVariables.SKIP_VALUE;
              }
            });
  }
  private Object[] resolveInitBinderArguments(
      Object handler, Method initBinderMethod, WebDataBinder binder, NativeWebRequest webRequest)
      throws Exception {

    Class[] initBinderParams = initBinderMethod.getParameterTypes();
    Object[] initBinderArgs = new Object[initBinderParams.length];

    for (int i = 0; i < initBinderArgs.length; i++) {
      MethodParameter methodParam = new MethodParameter(initBinderMethod, i);
      methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
      GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
      String paramName = null;
      boolean paramRequired = false;
      String paramDefaultValue = null;
      String pathVarName = null;
      Annotation[] paramAnns = methodParam.getParameterAnnotations();

      for (Annotation paramAnn : paramAnns) {
        if (RequestParam.class.isInstance(paramAnn)) {
          RequestParam requestParam = (RequestParam) paramAnn;
          paramName = requestParam.value();
          paramRequired = requestParam.required();
          paramDefaultValue = requestParam.defaultValue();
          break;
        } else if (ModelAttribute.class.isInstance(paramAnn)) {
          throw new IllegalStateException(
              "@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod);
        } else if (PathVariable.class.isInstance(paramAnn)) {
          PathVariable pathVar = (PathVariable) paramAnn;
          pathVarName = pathVar.value();
        }
      }

      if (paramName == null && pathVarName == null) {
        Object argValue = resolveCommonArgument(methodParam, webRequest);
        if (argValue != WebArgumentResolver.UNRESOLVED) {
          initBinderArgs[i] = argValue;
        } else {
          Class paramType = initBinderParams[i];
          if (paramType.isInstance(binder)) {
            initBinderArgs[i] = binder;
          } else if (BeanUtils.isSimpleProperty(paramType)) {
            paramName = "";
          } else {
            throw new IllegalStateException(
                "Unsupported argument ["
                    + paramType.getName()
                    + "] for @InitBinder method: "
                    + initBinderMethod);
          }
        }
      }

      if (paramName != null) {
        initBinderArgs[i] =
            resolveRequestParam(
                paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null);
      } else if (pathVarName != null) {
        initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null);
      }
    }

    return initBinderArgs;
  }
  @SuppressWarnings("unchecked")
  private Object[] resolveHandlerArguments(
      Method handlerMethod,
      Object handler,
      NativeWebRequest webRequest,
      ExtendedModelMap implicitModel)
      throws Exception {

    Class[] paramTypes = handlerMethod.getParameterTypes();
    Object[] args = new Object[paramTypes.length];

    for (int i = 0; i < args.length; i++) {
      MethodParameter methodParam = new MethodParameter(handlerMethod, i);
      methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
      GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
      String paramName = null;
      String headerName = null;
      boolean requestBodyFound = false;
      String cookieName = null;
      String pathVarName = null;
      String attrName = null;
      boolean required = false;
      String defaultValue = null;
      boolean validate = false;
      int found = 0;
      Annotation[] paramAnns = methodParam.getParameterAnnotations();

      for (Annotation paramAnn : paramAnns) {
        if (RequestParam.class.isInstance(paramAnn)) {
          RequestParam requestParam = (RequestParam) paramAnn;
          paramName = requestParam.value();
          required = requestParam.required();
          defaultValue = requestParam.defaultValue();
          found++;
        } else if (RequestHeader.class.isInstance(paramAnn)) {
          RequestHeader requestHeader = (RequestHeader) paramAnn;
          headerName = requestHeader.value();
          required = requestHeader.required();
          defaultValue = requestHeader.defaultValue();
          found++;
        } else if (RequestBody.class.isInstance(paramAnn)) {
          requestBodyFound = true;
          found++;
        } else if (CookieValue.class.isInstance(paramAnn)) {
          CookieValue cookieValue = (CookieValue) paramAnn;
          cookieName = cookieValue.value();
          required = cookieValue.required();
          defaultValue = cookieValue.defaultValue();
          found++;
        } else if (PathVariable.class.isInstance(paramAnn)) {
          PathVariable pathVar = (PathVariable) paramAnn;
          pathVarName = pathVar.value();
          found++;
        } else if (ModelAttribute.class.isInstance(paramAnn)) {
          ModelAttribute attr = (ModelAttribute) paramAnn;
          attrName = attr.value();
          found++;
        } else if (Value.class.isInstance(paramAnn)) {
          defaultValue = ((Value) paramAnn).value();
        } else if ("Valid".equals(paramAnn.annotationType().getSimpleName())) {
          validate = true;
        }
      }

      if (found > 1) {
        throw new IllegalStateException(
            "Handler parameter annotations are exclusive choices - "
                + "do not specify more than one such annotation on the same parameter: "
                + handlerMethod);
      }

      if (found == 0) {
        Object argValue = resolveCommonArgument(methodParam, webRequest);
        if (argValue != WebArgumentResolver.UNRESOLVED) {
          args[i] = argValue;
        } else if (defaultValue != null) {
          args[i] = resolveDefaultValue(defaultValue);
        } else {
          Class paramType = methodParam.getParameterType();
          if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
            args[i] = implicitModel;
          } else if (SessionStatus.class.isAssignableFrom(paramType)) {
            args[i] = this.sessionStatus;
          } else if (Errors.class.isAssignableFrom(paramType)) {
            throw new IllegalStateException(
                "Errors/BindingResult argument declared "
                    + "without preceding model attribute. Check your handler method signature!");
          } else if (BeanUtils.isSimpleProperty(paramType)) {
            paramName = "";
          } else {
            attrName = "";
          }
        }
      }

      if (paramName != null) {
        args[i] =
            resolveRequestParam(
                paramName, required, defaultValue, methodParam, webRequest, handler);
      } else if (headerName != null) {
        args[i] =
            resolveRequestHeader(
                headerName, required, defaultValue, methodParam, webRequest, handler);
      } else if (requestBodyFound) {
        args[i] = resolveRequestBody(methodParam, webRequest, handler);
      } else if (cookieName != null) {
        args[i] =
            resolveCookieValue(
                cookieName, required, defaultValue, methodParam, webRequest, handler);
      } else if (pathVarName != null) {
        args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
      } else if (attrName != null) {
        WebDataBinder binder =
            resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
        boolean assignBindingResult =
            (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
        if (binder.getTarget() != null) {
          doBind(binder, webRequest, validate, !assignBindingResult);
        }
        args[i] = binder.getTarget();
        if (assignBindingResult) {
          args[i + 1] = binder.getBindingResult();
          i++;
        }
        implicitModel.putAll(binder.getBindingResult().getModel());
      }
    }

    return args;
  }
  /**
   * 得到参数列表
   *
   * @param method
   * @param model
   * @param request
   * @param response
   * @param c
   * @return
   */
  @SuppressWarnings("unchecked")
  public static Object[] getArgs(
      Method method,
      Map<String, Object> model,
      HttpServletRequest request,
      HttpServletResponse response,
      Class<?> c) {
    Class<?>[] paramTypes = method.getParameterTypes();
    Object[] args = new Object[paramTypes.length];
    Map<String, Object> argMap = new HashMap<String, Object>(args.length);
    Map<String, String> pathValues = null;
    PathPattern pathPattern = method.getAnnotation(PathPattern.class);
    if (pathPattern != null) {
      String path = request.getRequestURI();
      int index = path.lastIndexOf('.');
      if (index != -1) {
        path = path.substring(0, index);
        String[] patterns = pathPattern.patterns();
        pathValues = getPathValues(patterns, path);
      }
    }
    MapBindingResult errors = new MapBindingResult(argMap, "");
    ParameterNameDiscoverer parameterNameDiscoverer =
        new LocalVariableTableParameterNameDiscoverer();
    for (int i = 0; i < paramTypes.length; i++) {
      Class<?> paramType = paramTypes[i];

      MethodParameter methodParam = new MethodParameter(method, i);
      methodParam.initParameterNameDiscovery(parameterNameDiscoverer);
      GenericTypeResolver.resolveParameterType(methodParam, c.getClass());

      String paramName = methodParam.getParameterName();
      // map
      if (Map.class.isAssignableFrom(paramType)) {
        args[i] = model;
      }
      // HttpServletRequest
      else if (HttpServletRequest.class.isAssignableFrom(paramType)) {
        args[i] = request;
      }
      // HttpServletResponse
      else if (HttpServletResponse.class.isAssignableFrom(paramType)) {
        args[i] = response;
      }
      // HttpSession
      else if (HttpSession.class.isAssignableFrom(paramType)) {
        args[i] = request.getSession();
      }
      // Errors
      else if (Errors.class.isAssignableFrom(paramType)) {
        args[i] = errors;
      }
      // MultipartFile
      else if (MultipartFile.class.isAssignableFrom(paramType)) {
        MultipartFile[] files = resolveMultipartFiles(request, errors, paramName);
        if (files != null && files.length > 0) {
          args[i] = files[0];
        }
      }
      // MultipartFile[]
      else if (MultipartFile[].class.isAssignableFrom(paramType)) {
        args[i] = resolveMultipartFiles(request, errors, paramName);
      } else {
        // 简单数据类型
        if (BeanUtils.isSimpleProperty(paramType)) {
          SimpleTypeConverter converter = new SimpleTypeConverter();
          Object value;
          // 是否是数组
          if (paramType.isArray()) {
            value = request.getParameterValues(paramName);
          } else {
            Object[] parameterAnnotations = methodParam.getParameterAnnotations();
            value = null;
            if (parameterAnnotations != null && parameterAnnotations.length > 0) {
              if (pathValues != null && pathValues.size() > 0) {
                for (Object object : parameterAnnotations) {
                  if (PathVariable.class.isInstance(object)) {
                    PathVariable pv = (PathVariable) object;
                    if (StringUtils.isEmpty(pv.value())) {
                      value = pathValues.get(paramName);
                    } else {
                      value = pathValues.get(pv.value());
                    }
                    break;
                  }
                }
              }
            } else {
              value = request.getParameter(paramName);
            }
          }
          try {
            args[i] = converter.convertIfNecessary(value, paramType, methodParam);
            model.put(paramName, args[i]);
          } catch (TypeMismatchException e) {
            errors.addError(new FieldError(paramName, paramName, e.getMessage()));
          }
        } else {
          // 复杂数据类型POJO类
          if (paramType.isArray()) {
            ObjectArrayDataBinder binder =
                new ObjectArrayDataBinder(paramType.getComponentType(), paramName);
            args[i] = binder.bind(request);
            model.put(paramName, args[i]);
          } else {
            Object bindObject = BeanUtils.instantiateClass(paramType);
            SummerServletRequestDataBinder binder =
                new SummerServletRequestDataBinder(bindObject, paramName);
            binder.bind(request);
            BindException be = new BindException(binder.getBindingResult());
            List<FieldError> fieldErrors = be.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
              errors.addError(fieldError);
            }
            args[i] = binder.getTarget();
            model.put(paramName, args[i]);
          }
        }
      }
    }
    return args;
  }