SpringMVC-解析@PathVariable

DispatcherServlet.doService去处理请求时,调用getHandler去获取匹配请求的handle。会调用RequestMappingInfoHandlerMapping.handleMatch,这个方法会调用extractMatchDetails解析uri模板变量,MATRIX变量,并将解析后的值设置到request的属性中。

RequestMappingInfoHandlerMapping.extractMatchDetails(
PatternsRequestCondition condition, String lookupPath, HttpServletRequest request)

private void extractMatchDetails(
		PatternsRequestCondition condition, String lookupPath, HttpServletRequest request) {

	String bestPattern;
	Map<String, String> uriVariables;
	if (condition.isEmptyPathMapping()) {
		bestPattern = lookupPath;
		uriVariables = Collections.emptyMap();
	}
	else {
		bestPattern = condition.getPatterns().iterator().next();
		uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
		if (!getUrlPathHelper().shouldRemoveSemicolonContent()) {
			request.setAttribute(MATRIX_VARIABLES_ATTRIBUTE, extractMatrixVariables(request, uriVariables));
		}
		uriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables);
	}
	request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
	request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
}

extractUriTemplateVariables将匹配到的handle的处理请求路径和传过来的请求路径对比,将路径中的{}里面的参数和客户的请求路径对比后放到Map中返回。例如匹配路径是/testPath/{value},请求路径是/testPath/123,则Map中的值是value->123.decodePathVariables对uri模板变量值进行解码。调用request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);将uri模板变量值设置到request的属性中。

DispatcherServlet的doService方法调用handle处理request。会调用InvocableHandlerMethod.invokeForRequest处理request。

InvocableHandlerMethod.invokeForRequest

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

	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	if (logger.isTraceEnabled()) {
		logger.trace("Arguments: " + Arrays.toString(args));
	}
	return doInvoke(args);
}

1、getMethodArgumentValues解析参数。
2、doInvoke执行处理方法。

InvocableHandlerMethod.getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) 的执行流程和@@RequestParam的解析一致。

AbstractNamedValueMethodArgumentResolver.getNamedValueInfo(MethodParameter parameter)

	private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
	NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
	if (namedValueInfo == null) {
		namedValueInfo = createNamedValueInfo(parameter);
		namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
		this.namedValueInfoCache.put(parameter, namedValueInfo);
	}
	return namedValueInfo;
}

1、createNamedValueInfo解析参数注解的name属性
2、updateNamedValueInfo判断解析后的name是否存在,不存在则获取参数名作为name,并将name,required,defaultValue封装成NamedValueInfo。

PathVariableMethodArgumentResolver.createNamedValueInfo(MethodParameter parameter)

protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
	PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);
	Assert.state(ann != null, "No PathVariable annotation");
	return new PathVariableNamedValueInfo(ann);
}

PathVariableNamedValueInfo(PathVariable annotation)

public PathVariableNamedValueInfo(PathVariable annotation) {
		super(annotation.name(), annotation.required(), ValueConstants.DEFAULT_NONE);
	}

createNamedValueInfo解析@PathVariable的name,required属性。并设置默认值为DEFAULT_NONE。并封装成NamedValueInfo。

PathVariableMethodArgumentResolver.resolveName重写了父类AbstractNamedValueMethodArgumentResolver.resolveName方法。

PathVariableMethodArgumentResolver.resolveName(String name, MethodParameter parameter, NativeWebRequest request)

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);
}

从request中获取uri模板变量属性,并从属性中获取值。

posted @ 2022-11-12 13:26  shigp1  阅读(174)  评论(0编辑  收藏  举报