springMVC分析-3

springMVC的handlerAdapter处理

参数转换,数据绑定,参数验证

springMVC 3.1以后,其注册的是RequestMappingHandlerAdapter,来看看这个类

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
    implements BeanFactoryAware, InitializingBean {

private static final boolean completionStagePresent = ClassUtils.isPresent("java.util.concurrent.CompletionStage",
        RequestMappingHandlerAdapter.class.getClassLoader());


private List<HandlerMethodArgumentResolver> customArgumentResolvers;

private HandlerMethodArgumentResolverComposite argumentResolvers;

private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;

private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;

private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

private List<ModelAndViewResolver> modelAndViewResolvers;

private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();

private List<HttpMessageConverter<?>> messageConverters;

private List<Object> requestResponseBodyAdvice = new ArrayList<Object>();

private WebBindingInitializer webBindingInitializer;

private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");

private Long asyncRequestTimeout;

private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];

private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];

private boolean ignoreDefaultModelOnRedirect = false;

private int cacheSecondsForSessionAttributeHandlers = 0;

private boolean synchronizeOnSession = false;

private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();

private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

private ConfigurableBeanFactory beanFactory;


private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache =
        new ConcurrentHashMap<Class<?>, SessionAttributesHandler>(64);

private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<Class<?>, Set<Method>>(64);

private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache =
        new LinkedHashMap<ControllerAdviceBean, Set<Method>>();

private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<Class<?>, Set<Method>>(64);

private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache =
        new LinkedHashMap<ControllerAdviceBean, Set<Method>>();

}

这个类是个适配器模式,其包含了大量的解析器。而这个类实现了InitializingBean,在其被spring实例化时,会调用afterPropertiesSet()方法进行初始化,还有其在
解析出的节点,所有可以看出来afterPropertiesSet()是注册默认的解析器。

//构造函数
public RequestMappingHandlerAdapter() {
    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
    stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316

    this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
    this.messageConverters.add(new ByteArrayHttpMessageConverter());
    this.messageConverters.add(stringHttpMessageConverter);
    this.messageConverters.add(new SourceHttpMessageConverter<Source>());
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}

@Override
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    initControllerAdviceCache();

    //参数解析
    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    //参数绑定
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    //返回值处理
    if (this.returnValueHandlers == null) {
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}

看initConstrllerAdviceCache()这个方法,

private void initControllerAdviceCache() {
    if (getApplicationContext() == null) {
        return;
    }

    //从beanFactory找出所有的ControllerAdvice注解的bean,并将ControllerAdvice注解中的参数解析出来,并封装到ControllerAdviceBean
    List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
    //排序
    AnnotationAwareOrderComparator.sort(beans);

    List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();


    for (ControllerAdviceBean bean : beans) {

        // @ModelAttribute 注解的方法
        Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
        if (!attrMethods.isEmpty()) {
            this.modelAttributeAdviceCache.put(bean, attrMethods);
            logger.info("Detected @ModelAttribute methods in " + bean);
        }

        //@InitBinder 注解的方法
        Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
        if (!binderMethods.isEmpty()) {
            this.initBinderAdviceCache.put(bean, binderMethods);
            logger.info("Detected @InitBinder methods in " + bean);
        }

        //判断RequestBodyAdvice 是否是bean的父类
        if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
            requestResponseBodyAdviceBeans.add(bean);
            logger.info("Detected RequestBodyAdvice bean in " + bean);
        }
        if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
            requestResponseBodyAdviceBeans.add(bean);
            logger.info("Detected ResponseBodyAdvice bean in " + bean);
        }
    }

    if (!requestResponseBodyAdviceBeans.isEmpty()) {
        this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
    }
}

初始化这些adviceBean做什么的呢?我们继续玩下看,看RequestMappingHandlerAdapter的处理方法,在DispacherServlet里面的方法

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

然后调用RequestMappingHandlerAdapter的父类AbstractHandlerMethodAdapter的handler方法进行处理,而这个handler方法,直接转给了handleInternal()这个方法,这个方法是个抽象方法,故其具体实现在其子类,我们看RequestMappingHandlerAdapter的具体实现

@Override
protected ModelAndView handleInternal(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    //检查是否支持该请求方法,如get,post这类的,以及requirdSession
    checkRequest(request);

    //检查是否包含@SessionAttributes 这个注解在handlerMethod的bean中,如有则配置header中的Cache-Control,默认是no-store
    if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
        applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
    }
    else {
        //设置Cache-Control
        prepareResponse(response);
    }

    // Execute invokeHandlerMethod in synchronized block if required.
    //请求是否需要根据session来加锁,默认是false
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                return invokeHandlerMethod(request, response, handlerMethod);
            }
        }
    }

    //处理方法
    return invokeHandlerMethod(request, response, handlerMethod);
}

再往后面的处理方法看

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    ServletWebRequest webRequest = new ServletWebRequest(request, response);

    WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
    ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

    //创建出ServletInvocableHandlerMethod 并初始化出@ResponseStatus里面的值
    ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
    //设置处理参数的聚合类,Composite
    invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

    //设置处理返回值的聚合类
    invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);


    invocableMethod.setDataBinderFactory(binderFactory);
    //设置解析方法中参数的解析器
    invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

    ModelAndViewContainer mavContainer = new ModelAndViewContainer();
    mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
    modelFactory.initModel(webRequest, mavContainer, invocableMethod);
    mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

    AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
    asyncWebRequest.setTimeout(this.asyncRequestTimeout);

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.setTaskExecutor(this.taskExecutor);
    asyncManager.setAsyncWebRequest(asyncWebRequest);
    asyncManager.registerCallableInterceptors(this.callableInterceptors);
    asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

    if (asyncManager.hasConcurrentResult()) {
        Object result = asyncManager.getConcurrentResult();
        mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
        asyncManager.clearConcurrentResult();
        if (logger.isDebugEnabled()) {
            logger.debug("Found concurrent result value [" + result + "]");
        }
        invocableMethod = invocableMethod.wrapConcurrentResult(result);
    }

    invocableMethod.invokeAndHandle(webRequest, mavContainer);
    if (asyncManager.isConcurrentHandlingStarted()) {
        return null;
    }

    return getModelAndView(mavContainer, modelFactory, webRequest);
}

从这个方法中,我们需要看的是请求参数是如何绑定到方法参数上的

WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); 

从上面可以看出来其生成了一个WebDataBinderFactory 的参数绑定工厂,来看看这个工厂是怎么生成的

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
    Class<?> handlerType = handlerMethod.getBeanType();
    //从初始化的缓存中取
    Set<Method> methods = this.initBinderCache.get(handlerType);
    if (methods == null) {
        //找出在该controller中的@InitBinder的方法,并加入缓存中,这个缓存是个ConcurrentHashMap
        methods = HandlerMethodSelector.selectMethods(handlerType, INIT_BINDER_METHODS);
        this.initBinderCache.put(handlerType, methods);
    }
    List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
    //从全局的@InitBinder中取,在@ConstrollerAdvice中配置的@InitBinder方法
    for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache .entrySet()) {
        if (entry.getKey().isApplicableToBeanType(handlerType)) {
            Object bean = entry.getKey().resolveBean();
            for (Method method : entry.getValue()) {
                initBinderMethods.add(createInitBinderMethod(bean, method));
            }
        }
    }
    //将上面两种聚合
    for (Method method : methods) {
        Object bean = handlerMethod.getBean();
        initBinderMethods.add(createInitBinderMethod(bean, method));
    }
    // 并和RequestMappingHandlerAdapter的ConfigurableWebBindingInitializer
    return createDataBinderFactory(initBinderMethods);
}

//ConfigurableWebBindingInitializer包含的属性

public class ConfigurableWebBindingInitializer implements WebBindingInitializer {

    private boolean autoGrowNestedPaths = true;

    private boolean directFieldAccess = false;

    private MessageCodesResolver messageCodesResolver;

    private BindingErrorProcessor bindingErrorProcessor;

    private Validator validator;

    private ConversionService conversionService;

    private PropertyEditorRegistrar[] propertyEditorRegistrars;
}

可以看出这个WebDataBinderFactory 包含了自定义的数据绑定方法还有springMVC默认注册的,以及Validator.
有了WebDataBinderFactory,继续分析其是如何使用的。

public void invokeAndHandle(ServletWebRequest webRequest,
        ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    //得到controller的返回值
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    setResponseStatus(webRequest);

    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(this.responseReason)) {
        mavContainer.setRequestHandled(true);
        return;
    }

    mavContainer.setRequestHandled(false);
    try {
        //交给returnValueHandlers进行处理
        this.returnValueHandlers.handleReturnValue(
                returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
}

来看看是如何获取到controller的返回值,中间做了哪些处理

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

    //获取到该方法的入参
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        StringBuilder sb = new StringBuilder("Invoking [");
        sb.append(getBeanType().getSimpleName()).append(".");
        sb.append(getMethod().getName()).append("] method with arguments ");
        sb.append(Arrays.asList(args));
        logger.trace(sb.toString());
    }
    //使用反射调用该controller的具体处理方法
    Object returnValue = doInvoke(args);
    if (logger.isTraceEnabled()) {
        logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
    }
    return returnValue;
}

我们可以看到整个流程下来,数据绑定的处理就在InvocableHandlerMethod中的getMethodArgumentValues()方法中

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {

    MethodParameter[] parameters = getMethodParameters();
    Object[] args = new Object[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
        MethodParameter parameter = parameters[i];
        parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
        GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
        args[i] = resolveProvidedArgument(parameter, providedArgs);
        if (args[i] != null) {
            continue;
        }
        if (this.argumentResolvers.supportsParameter(parameter)) {
            try {
                args[i] = this.argumentResolvers.resolveArgument(
                        parameter, mavContainer, request, this.dataBinderFactory);
                continue;
            }
            catch (Exception ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
                }
                throw ex;
            }
        }
        if (args[i] == null) {
            String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
            throw new IllegalStateException(msg);
        }
    }
    return args;
}

可以看到,其最后交给了 HandlerMethodArgumentResolverComposite 这个 HandlerMethodArgumentResolver的聚合类处理

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

    //根据参数获取到具体的解析类
    HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
    if (resolver == null) {
        throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
    }
    //解析类解析
    return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}

可以看出这又有一个扩展点 HandlerMethodArgumentResolver,我们可以实现这个接口,自定义出解析类。
在HandlerMethodArgumentResolver 实现了对参数类型的转换,格式转换,以及验证的操作。默认注册的HandlerMethodArgumentResolver 有哪些呢

org.springframework.web.method.annotation.RequestParamMethodArgumentResolver

org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver

org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver

org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver

org.springframework.web.method.annotation.RequestParamMethodArgumentResolver

继续在看获得controller的返回值后,然后交给了HandlerMethodReturnValueHandlerComposite 对返回值进行处理,比如像注解为@ResponseBody的,则交给RequestResponseBodyMethodProcessor进行处理,可以看出这又是个一个扩展点,其可以用来对controller的返回值进行再处理。其默认注册的HandlerMethodReturnValueHandler有以下,按以下顺序进行匹配,最先匹配原则

//处理返回ModelAndView的
org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler


org.springframework.web.method.annotation.ModelMethodProcessor

//处理返回的参数是View的子类的
org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler

//请求返回HttpEntity的
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor

org.springframework.web.servlet.mvc.method.annotation.HttpHeadersReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.AsyncTaskMethodReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.ListenableFutureReturnValueHandler

org.springframework.web.servlet.mvc.method.annotation.CompletionStageReturnValueHandler

//处理方法上包含@ModelAttribute的
org.springframework.web.method.annotation.ModelAttributeMethodProcessor

//处理包含这个@ResponseBody
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor

//处理返回string类型的视图,已经重定向,转发
org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler

//处理返回值是Map的子类
org.springframework.web.method.annotation.MapMethodProcessor

转载于:https://www.cnblogs.com/myzhong2014/p/5312241.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值