一次请求的源码分析过程

来源:互联网 发布:化工项目网络计划绘制 编辑:程序博客网 时间:2024/06/06 08:35

一次请求的源码分析过程

<!-- **********************下次处理:为什么我们请求后,解析处理返回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> -->
原创粉丝点击