1.@PathVariable的解析
org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
支持26种参数类型
if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); }
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; }
//这个方法来处理@PathVariable
org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver#supportsParameter
@Override public boolean supportsParameter(MethodParameter parameter) { //主要是判断参数是否有@PathVariable注解 if (!parameter.hasParameterAnnotation(PathVariable.class)) { return false; } if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) { PathVariable pathVariable = parameter.getParameterAnnotation(PathVariable.class); return (pathVariable != null && StringUtils.hasText(pathVariable.value())); } return true; }
通过PathVariableMethodArgumentResolver来处理参数
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }
org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver#resolveArgument
org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver#resolveName
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { //这里为什么能获取到值?不明白 Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); return (uriTemplateVars != null ? uriTemplateVars.get(name) : null); }
2.@RequestParam 参数解析
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver#supportsParameter
判断参数上是否有@RequestParam注解
public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(RequestParam.class)) { if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) { RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class); return (requestParam != null && StringUtils.hasText(requestParam.name())); } else { return true; } }
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver#resolveName
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); if (servletRequest != null) { Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest); if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) { return mpArg; } } Object arg = null; MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class); if (multipartRequest != null) { List<MultipartFile> files = multipartRequest.getFiles(name); if (!files.isEmpty()) { arg = (files.size() == 1 ? files.get(0) : files); } } if (arg == null) { //获取url里面的参数 String[] paramValues = request.getParameterValues(name); if (paramValues != null) { arg = (paramValues.length == 1 ? paramValues[0] : paramValues); } } return arg; }
总结:@RequestParam解决核心: 初始化后吧@RequestParam里面的name放入methodparam,然后通过RequestParamMethodArgumentResolver把请求url里面的参数放入args[],然后通过反射进入业务层,
@RequestParam后面的参数没有用,主要是url后面的参数和name里面的参数一致即可