一次请求的源码分析过程

一次请求的源码分析过程

<!-- **********************下次处理:为什么我们请求后,解析处理返回ModelAndView,那为什么我们有时候在请求controller后返回一个json数据,有的是一个页面,
        这块springmvc是怎么处理的,是否支持一些别的扩展,
     -->

    <!--
        最后 ****
        拿到中置拦截器处理得到的ModelAndView 处理程序选择和处理程序调用的结果 模型和视图,或者是一个可以解析为模型和视图的异常。
        DispatcherServlet.processDispatchResult();
        //处理数据请求响应处理结束,http连接断开,释放资源
      -->

    <!-- 
        过后就是中置拦截器
        interceptor.postHandle

        视图解析器,从ModelAndView中解析
        ViewResolve

        后置拦截器(关闭连接,释放资源)
        interceptor.afterCompleton

     -->

    <!-- 
        HandlerAdapter.handle()
        适配器去调用具体的controller处理器

        // 实际调用处理程序。
        ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        RequestMappingHandlerAdapter.invokeHandleMethod() //去调用这个实际的HandleMethod,就是方法调用

        //注定参数解析多种多样
        InvocableHandlerMethod.getMethodArgumentValues() //获取这些method方法参数的值,并解析处理
        //拿到所有参数
        MethodParameter[] parameters = getMethodParameters();

        //请求通过requst对象中传入入参值,封装成数组,拿到之前的method对象,通过method.invoke(bean, args); //arg数组来调用具体的方法


        //可以扩展,不同的参数类型对应不同的处理类*** 重要
        // 参数解析处理逻辑
        if (this.argumentResolvers.supportsParameter(parameter)) {
            try {
                args[i] = this.argumentResolvers.resolveArgument(
                        parameter, mavContainer, request, this.dataBinderFactory);
                continue;
            }
            catch (Exception ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
                }
                throw ex;
            }
        }

        HandlerMethodArgumentResolver //扩展解析参数处理类的最顶层接口

        //argumentResolvers 这个是什么时候初始化的,是在启动的时候初始化的,也是通过initBean来加载初始化注册的
        //解答:在这个类中通过InitializingBean来初始化的
        public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
        implements BeanFactoryAware, InitializingBean {

        getDefaultArgumentResolvers //这个方法完成初始化

        HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
        if (result == null) {
            for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
                            parameter.getGenericParameterType() + "]");
                }
                if (methodArgumentResolver.supportsParameter(parameter)) {
                    result = methodArgumentResolver;
                    this.argumentResolverCache.put(parameter, result);
                    break;
                }
            }
        }
        //通过这个methodArgumentResolver.supportsParameter(parameter) 可以查看到默认支持的参数解析有哪些
        if (methodArgumentResolver.supportsParameter(parameter)) {
            result = methodArgumentResolver;
            this.argumentResolverCache.put(parameter, result);
            break;
        }

        //获取request中的参数,并解析处理参数,处理完返回请求参数去调用具体的method方法,通过invoke
        Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
        Object returnValue = invoke(args);

        private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
            ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
            modelFactory.updateModel(webRequest, mavContainer);
            if (mavContainer.isRequestHandled()) {
                return null;
            }
            ModelMap model = mavContainer.getModel(); //ModelAndViewContainer的封装
            ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
            if (!mavContainer.isViewReference()) {
                mav.setView((View) mavContainer.getView());
            }
            if (model instanceof RedirectAttributes) {
                Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
                HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
                RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
            }
            return mav; //返回结果集和页面
        }


        ModelAndView //再给后置拦截器去显示解析返回给浏览器


     -->

    <!-- 
        前置拦截器,拦截请求,truefalse
        当mappedHandler.applyPreHandle(processedRequest, response)返回false,就不往下执行了
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
        }
     -->

    <!-- 
        handlerAdapter - 负责去调用具体的controller里面的方法的,contrller中有多个方法,handlerAdapter去决定调用哪个方法
        适配参数,如何二个参数的方法,三个参数的方法,参数的格式和类型肯定不一样,所有handlerAdapter可以解析我们的处理器
        方法的参数,这里使用的是一个策略模式
        和返回去参数的解析,返回参数的解析也是通过策略模式去解析返回参数,比如controller
        中不同方法的返回参数类型,如string void map 等

        //为当前请求确定处理程序适配器。
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        //这里会根据具体的HandlerMethod去找到一个具体的HandlerAdapter适配器,spring在启动的时候就会默认注册4个HandlerAdapter
        if (ha.supports(handler)) { //策略模式的使用,方便扩展,使用不同的handler可以循环去找到对应的HandlerAdapter
            return ha;
        }

        interceptorIndex //由于拦截器是一个链式结构

        //TODO 扩展拦截器的认识

        //调用每个拦截器的前置拦截器
        if (getInterceptors() != null) {
            for (int i = 0; i < getInterceptors().length; i++) {
                HandlerInterceptor interceptor = getInterceptors()[i];
                if (!interceptor.preHandle(request, response, this.handler)) { 
                    //1.首先先去调用这个拦截器的preHandle()方法
                    //当这个拦截器是怎么时候注册进来的,自定义要如何写???
                }
                this.interceptorIndex = i; //给所有的拦截器编号  0, 1 , 2
            }
        }
        //调用每个拦截器的中置拦截器
        for (int i = getInterceptors().length - 1; i >= 0; i ————) {
            HandlerInterceptor interceptor = getInterceptors()[i];
            interceptor.postHandle(request, response, this.handler, mv); 
            // 2.调用中置拦截器
            // 调用顺序  3, 2, 1

        //调用后置拦截器
        for (int i = this.interceptorIndex; i >= 0; i————) {
                HandlerInterceptor interceptor = getInterceptors()[i];
                try {
                    interceptor.afterCompletion(request, response, this.handler, ex);
                    //3. 调用后置拦截器
                    //调用顺序 3,2, 1
                }
                catch (Throwable ex2) {
                    logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
                }
            }

     -->

    <!-- 如: /session/login 请求路径
        /session 能确定一个controller
        /login 能确定一个method
        DispatcherServlet 本身就是一个servlet,所以请求过来首先会访问它父类FrameworkServlet.service()方法  > DispatcherServlet.doDispatch()
        mappedHandler = getHandler(processedRequest); //获取当前请求的处理器,并包装成HandlerExecutionChain
        //遍历启动时注册的handlerMappings 并为每一个handlerMappings包装成一个处理类
        for (HandlerMapping hm : this.handlerMappings) { handlerExecutionChain handler = hm.getHandler(request);}

        //查找给定请求的处理程序方法。
        AbstractHandlerMethodMapping.getHandlerInternal()
        //拿到请求url /session/login
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        //根据url来拿到HandlerMethod对象
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        //urlMap 是一个url和控制器中的方法 url:控制器方法类解析数值 map 就是url和HandlerMethod的映射,那是什么时候加上的注册,那肯定是在启动的时候就注册到map中的
        List<T> directPathMatches = this.urlMap.get(lookupPath);
        //handlerMethod中建立一个url和controller中login()方法定映射,那映射是什么时候建立的了,还是在容器初始化是就建立了
        Map<T, HandlerMethod> handlerMehod = this.handlerMethods();

        //this.handlerMethods() 是这个类中的一个map,这个抽象类继承了InitializingBean,重点落在这个类中了
        //所以会在实例化该类调用afterPropertiesSet().initHandlerMethods();这个方法来完成handlerMehod的初始化
        AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean

        //循环遍历在初始化时注册到容器的beans数据集合并遍历去判断存在@Controller和@RequestMapping的bean
        String[] beanNames

        //先通过beanName来获取容器中的Class<?>反射对象,并用Class对象来匹配是否存在如下二个注解的类
        @Override
        protected boolean isHandler(Class<?> beanType) {
            return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
                    (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
        }

        //判断过后,detectHandlerMethods(beanName);这个方法只会走带有注解的类
        //相当于过滤,因为只有控制器才有url和方法的映射
        for (String beanName : beanNames) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
                    isHandler(getApplicationContext().getType(beanName))){
                detectHandlerMethods(beanName);
            }
        }

        final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
        Method:CommitteeActivityController.AddInfo(param)
        T:
        {
            [/committee/activity//activity],
            methods=[GET],
            params=[],
            headers=[],
            consumes=[],
            produces=[],
            custom=[]
        }

        //先拿到对应类的Class对象,并获取该类下的所有方法
        //new MethodFilter() 采用匿名类的方式来过滤method
        Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
            @Override
            public boolean matches(Method method) {
                T mapping = getMappingForMethod(method, userType);
                if (mapping != null) {
                    mappings.put(method, mapping);
                    return true;
                }
                else {
                    return false;
                }
            }
        });

        //并注册到this.handlerMethods.put(mapping, newHandlerMethod); map中
        for (Method method : methods) {
            registerHandlerMethod(handler, method, mappings.get(method));
        }

        //将HandlerMethod封装到handlerExecutionChain中
        return getHandlerExecutionChain(handler, request);

        //TODO 10.10 propress doWith() 54:13

        //迭代继续寻找父类中的方法
        ReflectionUtils.doWithMethods() 
        if (clazz.getSuperclass() != null) {
            doWithMethods(clazz.getSuperclass(), mc, mf);
        }
        //迭代继续寻找接口的方法
        else if (clazz.isInterface()) {
            for (Class<?> superIfc : clazz.getInterfaces()) {
                doWithMethods(superIfc, mc, mf);
            }
        }

        //拿到带有@RequestMapping的方法,获取注解上的属性
        AbstractHandlerMethodMapping.getMappingForMethod()
        RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);

        //拿到注解上的属性
        String[] params() default {};

        //包装method的参数信息
        RequestMappingInfo info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
        //封装成实体
        return new RequestMappingInfo(
            new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
                    this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions),
            new RequestMethodsRequestCondition(annotation.method()),
            new ParamsRequestCondition(annotation.params()),
            new HeadersRequestCondition(annotation.headers()),
            new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
            new ProducesRequestCondition(annotation.produces(), annotation.headers(), this.contentNegotiationManager),
            customCondition);

        //先循环每一个bean,扫描到有@Controller和@RequestMapping注解的类,并扫描对应类中的所有方法(包括父类和接口的)
        //注册Map<Method, T>的对应关系,然后遍历这些newHandlerMethod把它和mapping T 建立map关系于handlerMethods中
        this.handlerMethods.put(mapping, newHandlerMethod);

        //请求过来就直接去注册的map中去找对应的url就能匹配到对应的类和类的信息

        //回归正常的请求流程(如上是启动的自动initBean接口时自动注册到map的初始化流程)4

        //根据请求的url去handlerMethods去获取对应的HandlerMethod对象
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);

        //将获取到的HandlerMethod又封装到Match对象中

        Object handler = getHandlerInternal(request); //拿到对应请求url的HandlerMethod对象

        //又将HandlerMethod 封装到HandlerExecutionChain
        return getHandlerExecutionChain(handler, request);

        //将所有的拦截器都添加到Handler处理器中
        chain.addInterceptors(getAdaptedInterceptors());

        HandlerInterceptor//类中存在前,中,后置拦截器

        // HandlerExecutionChain中有如下二个属性
        private final Object handler; //HandlerMethod
        private HandlerInterceptor[] interceptors; //拦截器
     -->

    <!-- 定义HandlerMapping(请求的url:handlerMethod【controller中的方法】)的对应关系
            这个关系都是第一次都是第一次请求过来以后就建立映射关系,并放到内存map中去,方便下次直接查找使用,
        1.先判断是否支持HandlerMapping
        2.从自定义实现HandlerMapping中去找子类
        3.从注册的bean中找id等于handlerMapping的HandlerMapping
        4.用默认的HandlerMapping来,是 spring自己配置,有二个默认配置
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> -->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值