Interface parameter analysis - based on map

I think this kind of parser is a complement to the interface based on a key parameter analysis, which relies on the relevant notes based on a key interface parameters resolution. Once upon a time you thought about whether full-time by @RequestParam to package into a Map, and then again own analysis? A processor to present the same class @ RequestHeader, @ PathVariable, @ MatrixVariable have given this ability -

1, PathVariableMapMethodArgumentResolver

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);
        return (ann != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&
                !StringUtils.hasText(ann.value()));
    }

    /**
     * Return a Map with all URI template variables or an empty map.
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
        @SuppressWarnings("unchecked")
        Map<String, String> uriTemplateVars =
                (Map<String, String>) webRequest.getAttribute(
                        HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        if (!CollectionUtils.isEmpty(uriTemplateVars)) {
            return new LinkedHashMap<>(uriTemplateVars);
        }
        else {
            return Collections.emptyMap();
        }
    }

1, note processor

  • It must be marked with the @PathVariableannotation, and the parameter type is a map

2, the parameter parsing

  • All of the parameters used paths filled return to Map

二、RequestParamMapMethodArgumentResolver

    @Override
	public boolean supportsParameter(MethodParameter parameter) {
		RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
		return (requestParam != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&
				!StringUtils.hasText(requestParam.name()));
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

		ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
		if (MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) {
			// MultiValueMap
			Class<?> valueType = resolvableType.as(MultiValueMap.class).getGeneric(1).resolve();
			if (valueType == MultipartFile.class) {
				MultipartRequest multipartRequest = MultipartResolutionDelegate.resolveMultipartRequest(webRequest);
				return (multipartRequest != null ? multipartRequest.getMultiFileMap() : new LinkedMultiValueMap<>(0));
			}
			else if (valueType == Part.class) {
				HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
				if (servletRequest != null && MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
					Collection<Part> parts = servletRequest.getParts();
					LinkedMultiValueMap<String, Part> result = new LinkedMultiValueMap<>(parts.size());
					for (Part part : parts) {
						result.add(part.getName(), part);
					}
					return result;
				}
				return new LinkedMultiValueMap<>(0);
			}
			else {
				Map<String, String[]> parameterMap = webRequest.getParameterMap();
				MultiValueMap<String, String> result = new LinkedMultiValueMap<>(parameterMap.size());
				parameterMap.forEach((key, values) -> {
					for (String value : values) {
						result.add(key, value);
					}
				});
				return result;
			}
		}

		else {
			// Regular Map
			Class<?> valueType = resolvableType.asMap().getGeneric(1).resolve();
			if (valueType == MultipartFile.class) {
				MultipartRequest multipartRequest = MultipartResolutionDelegate.resolveMultipartRequest(webRequest);
				return (multipartRequest != null ? multipartRequest.getFileMap() : new LinkedHashMap<>(0));
			}
			else if (valueType == Part.class) {
				HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
				if (servletRequest != null && MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
					Collection<Part> parts = servletRequest.getParts();
					LinkedHashMap<String, Part> result = new LinkedHashMap<>(parts.size());
					for (Part part : parts) {
						if (!result.containsKey(part.getName())) {
							result.put(part.getName(), part);
						}
					}
					return result;
				}
				return new LinkedHashMap<>(0);
			}
			else {
				Map<String, String[]> parameterMap = webRequest.getParameterMap();
				Map<String, String> result = new LinkedHashMap<>(parameterMap.size());
				parameterMap.forEach((key, values) -> {
					if (values.length > 0) {
						result.put(key, values[0]);
					}
				});
				return result;
			}
		}
	}

1, note processor

  • Use @RequestParamannotation, and the parameter type is a map

2, the parameter parsing

  • It can not pass a multiple-level key if the same key occurs, the value of the key top prevail. Map instance is an LinkedHashMap<String,String>instance of

2, case

 @ResponseBody
 @GetMapping("/test")
 public Object test(@RequestParam Map<String,Object> params) {
        System.out.println(params);
        return params;
 }

Search Path: /test?name=fsx&age=18&age=28console output is as follows:{name=fsx, age=18}

age can only take one of the values

3、RequestHeaderMapMethodArgumentResolver

The first-time request to get information: the type of expenditure data write MultiValueMap (LinkedMultiValueMap) / HttpHeaders / Map

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return (parameter.hasParameterAnnotation(RequestHeader.class) &&
				Map.class.isAssignableFrom(parameter.getParameterType()));
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

		Class<?> paramType = parameter.getParameterType();
		if (MultiValueMap.class.isAssignableFrom(paramType)) {
			MultiValueMap<String, String> result;
			if (HttpHeaders.class.isAssignableFrom(paramType)) {
				result = new HttpHeaders();
			}
			else {
				result = new LinkedMultiValueMap<>();
			}
			for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
				String headerName = iterator.next();
				String[] headerValues = webRequest.getHeaderValues(headerName);
				if (headerValues != null) {
					for (String headerValue : headerValues) {
						result.add(headerName, headerValue);
					}
				}
			}
			return result;
		}
		else {
			Map<String, String> result = new LinkedHashMap<>();
			for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
				String headerName = iterator.next();
				String headerValue = webRequest.getHeader(headerName);
				if (headerValue != null) {
					result.put(headerName, headerValue);
				}
			}
			return result;
		}
	}

1, note processor

  • It must be marked @RequestHeader, and the parameter is maptype

2, case

@ResponseBody
@GetMapping("/test")
public Object test(@RequestHeader Map<String, Object> headers) {
     headers.forEach((k, v) -> System.out.println(k + "-->" + v));
      return headers;
}

Console output:

host-->localhost:8080
connection-->keep-alive
cache-control-->max-age=0
upgrade-insecure-requests-->1
。。。。

But strongly recommended direct use Map, but the use of HttpHeaders type. So write @RequestHeader HttpHeaders headers, get a more convenient time.

4、MapMethodProcessor

It handles Map type, but does not mark any case annotations, after its execution order is very reliable, so a bit reveal all the details of the meaning.
The processor also explains: why write Map on your method to the Senate, HashMap, ModelMap and so on can be very convenient access to a cause value of the model ~

    @Override
	public boolean supportsParameter(MethodParameter parameter) {
		return Map.class.isAssignableFrom(parameter.getParameterType());
	}

	@Override
	@Nullable
	public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

		Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
		return mavContainer.getModel();
	}

1, note processor

  • The processor, the processing chain is on the spring of the parameter, the processing is marked no annotation maptype

2, the parameter parsing

  • The Model direct return

5、MatrixVariableMapMethodArgumentResolver

slightly.

Released two original articles · won praise 0 · Views 41

Guess you like

Origin blog.csdn.net/qq_41071876/article/details/104214777