【spring mvc】Spring MVC 的参数解析器ArgumentResolver阐述

谈及Spring MVC ,一定会记得spring mvc为应用程序提供的强大的参数绑定机制,那么我们今天来分析spring MVC如何为我们提供的参数解析器,以及这些参数解析器支持分别支持哪些参数类型.

一.当我们没有指定特别的HandlerAdapter的时候,spring-mvc会采用默认策略模式,使用RequestMappingHandlerAdapter类充当Adapter角色,

RequestMappingHandlerAdapter中有两个属性customArgumentResolvers,argumentResolvers,自定义参数解析器和默认的参数解析器。

默认参数解析器初始化如下代码所示:

public void afterPropertiesSet() {
        List handlers;
        if(this.argumentResolvers == null) {
            handlers = this.getDefaultArgumentResolvers();
            this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
        }

        if(this.initBinderArgumentResolvers == null) {
            handlers = this.getDefaultInitBinderArgumentResolvers();
            this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
        }

        if(this.returnValueHandlers == null) {
            handlers = this.getDefaultReturnValueHandlers();
            this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers);
        }

        this.initControllerAdviceCache();
    }
private List getDefaultArgumentResolvers() {
        ArrayList resolvers = new ArrayList();
        resolvers.add(new RequestParamMethodArgumentResolver(this.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(this.getMessageConverters()));
        resolvers.add(new RequestPartMethodArgumentResolver(this.getMessageConverters()));
        resolvers.add(new RequestHeaderMethodArgumentResolver(this.getBeanFactory()));
        resolvers.add(new RequestHeaderMapMethodArgumentResolver());
        resolvers.add(new ServletCookieValueMethodArgumentResolver(this.getBeanFactory()));
        resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory()));
        resolvers.add(new ServletRequestMethodArgumentResolver());
        resolvers.add(new ServletResponseMethodArgumentResolver());
        resolvers.add(new HttpEntityMethodProcessor(this.getMessageConverters()));
        resolvers.add(new RedirectAttributesMethodArgumentResolver());
        resolvers.add(new ModelMethodProcessor());
        resolvers.add(new MapMethodProcessor());
        resolvers.add(new ErrorsMethodArgumentResolver());
        resolvers.add(new SessionStatusMethodArgumentResolver());
        resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
        if(this.getCustomArgumentResolvers() != null) {
            resolvers.addAll(this.getCustomArgumentResolvers());
        }

        resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true));
        resolvers.add(new ServletModelAttributeMethodProcessor(true));
        return resolvers;
    }
自定义参数解析器,需要定义一个类并且实现HandlerMethodArgumentResolover类,然后在配置文件中添加该类的bean

二.默认参数解析器阐述

1>.RequestParamMethodArgumentResolver 这个解析器能够为参数上加了RequestParam注解的参数提供支持,请看如下代码

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		Class paramType = parameter.getParameterType();
		if (parameter.hasParameterAnnotation(RequestParam.class)) {
			if (Map.class.isAssignableFrom(paramType)) {
				String paramName = parameter.getParameterAnnotation(RequestParam.class).value();
				return StringUtils.hasText(paramName);
			}
			else {
				return true;
			}
		}
		else {
			if (parameter.hasParameterAnnotation(RequestPart.class)) {
				return false;
			}
			else if (MultipartFile.class.equals(paramType) || "javax.servlet.http.Part".equals(paramType.getName())) {
				return true;
			}
			else if (this.useDefaultResolution) {
				return BeanUtils.isSimpleProperty(paramType);
			}
			else {
				return false;
			}
		}
	}

2>.RequestParamMapMethodArgumentResolver,支持参数上加了RequestParam注解并且是Map类型的参数.

3>.PathVariableMethodArgumentResolver,支持参数上加了PathVariable注解并且不是Map类型的参数,

4>.PathVariableMapMethodArgumentResolver,支持参数上加了PathVariable注解并且参数类型为Map的参数,

5>.MatrixVariableMethodArgumentResolver.支持参数上加了MatrixVariable注解并且不是Map类型

6>.MatrixVariableMapMethodArgumentResolver,支持参数上加了MatrixVariable注解并且类型是Map的参数.

7>.ServletModelAttributeMethodProcessor.支持参数加了ModelAttribute注解的参数,

8>.RequestResponseBodyMethodProcessor支持参数上加了RequestBody注解的参数,

9>.RequestPartMethodArgumentResolver支持参数上了RequestPart注解的参数,代码如下:

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		if (parameter.hasParameterAnnotation(RequestPart.class)) {
			return true;
		}
		else {
			if (parameter.hasParameterAnnotation(RequestParam.class)){
				return false;
			}
			else if (MultipartFile.class.equals(parameter.getParameterType())) {
				return true;
			}
			else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
				return true;
			}
			else {
				return false;
			}
		}
	}

10>.RequestHeaderMethodArgumentResolver支持参数加了RequestHeader注解的并且不是Map类型的参数,

11>.RequestHeaderMapMethodArgumentResolver支持参数加了RequestHeader注解并且是Map类型的参数,

12>.ServletCookieValueMethodArgumentResolver支持参数上加了CookieValue注解的参数.

13>.ExpressionValueMethodArgumentResolver支持参数上加了Value注解的参数.

14>.ServletRequestMethodArgumentResolver支持代码如下:

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		Class paramType = parameter.getParameterType();
		return (WebRequest.class.isAssignableFrom(paramType) ||
				ServletRequest.class.isAssignableFrom(paramType) ||
				MultipartRequest.class.isAssignableFrom(paramType) ||
				HttpSession.class.isAssignableFrom(paramType) ||
				Principal.class.isAssignableFrom(paramType) ||
				Locale.class.equals(paramType) ||
				TimeZone.class.equals(paramType) ||
				"java.time.ZoneId".equals(paramType.getName()) ||
				InputStream.class.isAssignableFrom(paramType) ||
				Reader.class.isAssignableFrom(paramType) ||
				HttpMethod.class.equals(paramType));
	}

15>.ServletResponseMethodArgumentResolver支持代码如下:

Class paramType = parameter.getParameterType();
		return (ServletResponse.class.isAssignableFrom(paramType) ||
				OutputStream.class.isAssignableFrom(paramType) ||
				Writer.class.isAssignableFrom(paramType));

16>.HttpEntityMethodProcessor支持参数类型为HttpEntity或者RequestEntity类型的参数

17>.RedirectAttributesMethodArgumentResolver支持参数类型为RedirectAttributes的参数.

18>.ModelMethodProcessor支持参数是Model类型的参数

19>.MapMethodProcessor支持参数是Map类型的参数.

20>.ErrorsMethodArgumentResolver支持类型是Errors类型的参数

21>.SessionStatusMethodArgumentResolver支持参数类型是SessionStatus的参数.

22>.UriComponentsBuilderMethodArgumentResolver支持参数类型是UriComponentBuilder的参数.

以上是系统提供的默认的参数解析器。

下面是自定义参数解析器的例子。

public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        //判断参数是否是loginInfo的子类
        return LoginInfo.class.isAssignableFrom(methodParameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        return UserUtils.getUser();
    }
}
最主要的就是resolveArgument方法,supportsParmeter只是判断是否支持,因为spring会将所有的参数解析器在程序启动的时候加载到dispatcherServlet中,然后一个个的遍历判断。


你可能感兴趣的:(web架构)