SpringMVC重要接口(一)HandlerMethodArgumentResolver

在初学SpringMVC框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequestHttpServletResponse, 各种注解@RequestParam@RequestHeader@RequestBody@PathVariable@ModelAttribute等。相信很多初学者都曾经感慨过。

这其实都是org.springframework.web.method.support.HandlerMethodArgumentResolver的功劳。

这里写图片描述

这里写图片描述

package org.springframework.web.method.support;

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;

/**
 * Strategy interface for resolving method parameters into argument values in
 * the context of a given request.
 *
 * @author Arjen Poutsma
 * @since 3.1
 * @see HandlerMethodReturnValueHandler
 */
public interface HandlerMethodArgumentResolver {

    /**
     * Whether the given {@linkplain MethodParameter method parameter} is
     * supported by this resolver.
     * @param parameter the method parameter to check
     * @return {@code true} if this resolver supports the supplied parameter;
     * {@code false} otherwise
     */
    boolean supportsParameter(MethodParameter parameter);

    /**
     * Resolves a method parameter into an argument value from a given request.
     * A {@link ModelAndViewContainer} provides access to the model for the
     * request. A {@link WebDataBinderFactory} provides a way to create
     * a {@link WebDataBinder} instance when needed for data binding and
     * type conversion purposes.
     * @param parameter the method parameter to resolve. This parameter must
     * have previously been passed to {@link #supportsParameter} which must
     * have returned {@code true}.
     * @param mavContainer the ModelAndViewContainer for the current request
     * @param webRequest the current request
     * @param binderFactory a factory for creating {@link WebDataBinder} instances
     * @return the resolved argument value, or {@code null}
     * @throws Exception in case of errors with the preparation of argument values
     */
    Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

}

HandlerMethodArgumentResolver接口包含两个接口方法

  • supportsParameter

通过该方法我们如果需要对某个参数进行处理 只要此处返回true即可, 
通过MethodParameter可以获取该方法参数上的一些信息, 如方法参数中的注解信息等

public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @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 == paramType ||
                TimeZone.class == paramType ||
                "java.time.ZoneId".equals(paramType.getName()) ||
                InputStream.class.isAssignableFrom(paramType) ||
                Reader.class.isAssignableFrom(paramType) ||
                HttpMethod.class == paramType);
    }

public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver
        implements UriComponentsContributor {

    private static final TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (!parameter.hasParameterAnnotation(PathVariable.class)) {
            return false;
        }
        if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
            String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
            return StringUtils.hasText(paramName);
        }
        return true;
    }
  • resolveArgument 
    该方法就是对参数的解析,返回的Object会自动赋值到参数对象中。

这里写图片描述

这里写图片描述

这里写图片描述


SpringMVC自己的 
HandlerMethodArgumentResolver有哪些,并且会以什么样的顺序执行呢?

其实定义在RequestMappingHandlerAdapter里:

    /**
     * Return the list of argument resolvers to use including built-in resolvers
     * and custom resolvers provided via {@link #setCustomArgumentResolvers}.
     */
    private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

        // Annotation-based argument resolution
        resolvers.add(new RequestParamMethodArgumentResolver(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(getMessageConverters(), this.requestResponseBodyAdvice));
        resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
        resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
        resolvers.add(new RequestHeaderMapMethodArgumentResolver());
        resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
        resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
        resolvers.add(new SessionAttributeMethodArgumentResolver());
        resolvers.add(new RequestAttributeMethodArgumentResolver());

        // Type-based argument resolution
        resolvers.add(new ServletRequestMethodArgumentResolver());
        resolvers.add(new ServletResponseMethodArgumentResolver());
        resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
        resolvers.add(new RedirectAttributesMethodArgumentResolver());
        resolvers.add(new ModelMethodProcessor());
        resolvers.add(new MapMethodProcessor());
        resolvers.add(new ErrorsMethodArgumentResolver());
        resolvers.add(new SessionStatusMethodArgumentResolver());
        resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

        // Custom arguments
        if (getCustomArgumentResolvers() != null) {
            resolvers.addAll(getCustomArgumentResolvers());
        }

        // Catch-all
        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
        resolvers.add(new ServletModelAttributeMethodProcessor(true));

        return resolvers;
    }


HandlerMethodArgumentResolver子类 注解 or 类
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver @RequestParam
org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver @RequestParam
org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver @PathVariable
org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver @PathVariable
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver @MatrixVariable
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver @MatrixVariable
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor @ModelAttribute
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor @RequestBody
org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver @RequestPart
org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver @RequestHeader
org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver @RequestHeader
org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver @CookieValue
org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver @Value
org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver @SessionAttribute
org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver @RequestAttribute
org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver HttpServletRequest
org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver HttpServletResponse
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor HttpEntity
org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver RedirectAttributes
org.springframework.web.method.annotation.ModelMethodProcessor Model
org.springframework.web.method.annotation.MapMethodProcessor Map
org.springframework.web.method.annotation.ErrorsMethodArgumentResolver Errors
org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver SessionStatus
org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver UriComponentsBuilder


RequestMappingHandlerAdapter 被注册进去是使用了 <mvc:annotation-driven/> 注解,可参考我的这篇文章《SpringMVC 解读—— <mvc:annotation-driven/> 》。


这里写图片描述

这里我们就不再自己重新写一个了,我们采用SpringMVC自带的一个 
org.springframework.data.web.PageableHandlerMethodArgumentResolver

它将实现的功能如下:




绑定分页需要用到的参数,只是如何把这个Resolver注册进去呢,方式如下

<mvc:annotation-driven>
    <mvc:argument-resolvers>  
        <bean class="org.springframework.data.web.PageableHandlerMethodArgumentResolver"/>
    </mvc:argument-resolvers>
</mvc:annotation-driven>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值