栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringMvc执行流程源码分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringMvc执行流程源码分析

在先进行源码分析之前,首先将整个具体流程写在前面,先对整个流程有一个初步的了解之后再去进行分析相必会更加的容易理解,一些关键步骤在代码中有标注

SpringMvc执行流程源码分析
  • SpringMvc执行流程
  • 源码分析
    • 1.DispatcherServlet结构分析
    • 2.SpringMvc的九大组件
    • 3.锁定目标方法的执行
    • 4.invokeHandlerMethod执行细节
    • 5.如何确定方法每一个参数的值(方法括号中的参数)
    • 6.视图解析原理分析
    • 7.总结

SpringMvc执行流程



流程分析:

  1. 用户向服务器发送请求,请求被SpringMvc的前端控制器DispatcherServlet拦截;
  2. DispatcherServlet对请求的URL(统一资源定位符)进行解析,得到URI(请求资源标识符)然后根据URI,调用HandlerMapping获得Handler配置的所有相关对象,包括Handler对象以及Handler对象对应的拦截器,这些对象都会封装到一个HandlerExecutionChain对象当中返回;
  3. DispatcherServlet根据获取的Handler,选择一个合适的HandlerAdapter.HandlerAdapter的设计,符合面向对象的单一职责原则,代码结构清晰,便于维护,最为重要的是,代码的可复用性高,HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法;
  4. 提取请求中的模型数据,开始执行Handler(Controller).在填充Handler的入参过程中,根据配置,spring将帮助做一些额外的工作:
    消息转换:将请求消息,如json/xml等数据转换成一个对象,将对象展缓为指定的响应信息;
    数据转换:对请求信息进行数据转换,如string转换成integer,double等;
    数据格式换:对请求的信息进行数据格式转换,如将字符串转换为格式化数字和格式化日期;
    数据验证:验证数据的有效性,比如长度/格式等,验证结果存储到BindingResult或者ERROR中;
  5. Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中包含视图或视图模型;
  6. 根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet;
  7. ViewResolver结合Model和View来渲染视图;
  8. 将视图渲染结果返回给客户端。
源码分析 1.DispatcherServlet结构分析

请求一发首先会进去到doDispatch方法,下面是该方法源码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
 
        try {
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;
 
                try {
                     //检查是否文件上传请求
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                     //根据当前请求地址找到哪个类能来处理
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                          //如果没有找到哪个处理器能处理请求就会抛出异常
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                    
                    //拿到能执行这个类的所有适配器(反射工具,会进行反射执行)
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (this.logger.isDebugEnabled()) {
                            String requestUri = urlPathHelper.getRequestUri(request);
                            this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                        }
 
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
 
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
 
                    try {
                         //处理器的方法被调用,ha就是上面拿到的是配器,适配器来执行目标方法,
                          将目标方法执行后完成后的返回值作为视图名,设置保存在ModelAndView中,
                          目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装成ModelAndView
 
                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    } finally {
                        if (asyncManager.isConcurrentHandlingStarted()) {
                            return;
                        }
 
                    }
                   //如果没有视图名,设置默认的视图名
                    this.applyDefaultViewName(request, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var28) {
                    dispatchException = var28;
                }
                  //mappedHandler:目标处理器,mv:ModelAndView,processDispatchResult:进入到目标页面,而且ModelAndView的数据可以从请求域中获取
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            } catch (Exception var29) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
            } catch (Error var30) {
                this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
            }
 
        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                return;
            } else {
                if (multipartRequestParsed) {
                    this.cleanupMultipart(processedRequest);
                }
 
            }
        }
    }

大体流程
1.请求过来:DispatcherServlet收到请求
2.调用doDispatch()处理:

(1)this.getHandler()
根据当前请求地址找到能处理这个请求的目标处理类处理器)【根据当前请求在HandlerMapping中我到这个请求的映射信息,获取到目标处理器类】

(2)this.getHandlerAdapter()
根据当前处理器类获取到能执行这个处理器方法的适配盛【根据当前处理器类,找到类的HandlerAdapter《适配器)】
(3)使用刚才得到的适配器(AnnotationMethodHandlerAdapter)执行目标方法
(4)目标方法执行后返回一个ModelAndView对象
(5)根据ModelAndView的信息转发到具体的页面,并且可以在请求域中获取到ModelAndView中的模型数据

2.SpringMvc的九大组件

在SpringMvc工作的时候,关键位置都是由这些组件完成:

protected void initStrategies(ApplicationContext context) {
      //文件上传解析器:
   private MultipartResolver multipartResolver;
 
   //区域信息解析器,和国际化有关
    private LocaleResolver localeResolver;
 
    //主题解析器,强大的主题效果更换
    private ThemeResolver themeResolver;
 
    //handler映射信息:handlerMappings
    private List handlerMappings;
 
    //handler适配器
    private List handlerAdapters;
 
   //springMvc强大的异常解析功能:异常解析器
    private List handlerExceptionResolvers;
 
    //视图转换器:了解
    private RequestToViewNameTranslator viewNameTranslator;
   
    //springMvc中允许重定向携带数据的功能
    private FlashMapManager flashMapManager;
 
   //视图解析器
    private List viewResolvers;

    }

3.锁定目标方法的执行

执行的目标方法

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

会返回

return this.invokeHandlerMethod(request, response, handler);

下面是返回代码执行:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //拿到方法的解析器
        AnnotationMethodHandlerAdapter.ServletHandlerMethodResolver methodResolver = this.getMethodResolver(handler);
       //方法解析器根据当前请求地址找到真正的方法
        Method handlerMethod = methodResolver.resolveHandlerMethod(request);
         //创建一个方法执行器
        AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker methodInvoker = new                  AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker(methodResolver);
         //包装原生的 request, response
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
       //创建了一个隐含模型
        ExtendedModelMap implicitModel = new BindingAwareModelMap();
 
       //真正执行目标方法:目标方法利用放射执行期间确定参数值,提前执行modelattribute等所有的操作都在这个方法中
        Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
        
        ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
        methodInvoker.updateModelAttributes(handler, mav != null ? mav.getModel() : null, implicitModel, webRequest);
        return mav;
    }

4.invokeHandlerMethod执行细节
public final Object invokeHandlerMethod(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
        Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
 
        try {
            boolean debug = logger.isDebugEnabled();
            Iterator var7 = this.methodResolver.getActualSessionAttributeNames().iterator();
 
      
            while(var7.hasNext()) {
                String attrName = (String)var7.next();
                Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
                if (attrValue != null) {
                    implicitModel.addAttribute(attrName, attrValue);
                }
            }
 
            var7 = this.methodResolver.getModelAttributeMethods().iterator();
 
          //找到所有@ModelAttributeMethod注解标注的方法
            while(true) {
                Object[] args;
                String attrName;
                Method attributeMethodToInvoke;
                do {
                    if (!var7.hasNext()) {
                       //先确定ModelAttributeMethod方法执行时要使用的参数的值,解析传过来的参数
                        Object[] args = this.resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
                        if (debug) {
                            logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
                        }
 
                        ReflectionUtils.makeAccessible(handlerMethodToInvoke);
                       //执行目标方法
                        return handlerMethodToInvoke.invoke(handler, args);
                    }
 
                    Method attributeMethod = (Method)var7.next();
                    attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
                    //再次执行解析参数,会执行两次resolveHandlerArguments,一次是在方法上的注解参数,一次会执行解析方法中括号中的参数
                    args = this.resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
                    if (debug) {
                        logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
                    }
 
                    attrName = ((ModelAttribute)AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class)).value();
                } while(!"".equals(attrName) && implicitModel.containsAttribute(attrName));
 
                ReflectionUtils.makeAccessible(attributeMethodToInvoke);
                Object attrValue = attributeMethodToInvoke.invoke(handler, args);
                if ("".equals(attrName)) {
                    Class resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
                    attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
                }
 
               //把提前运行的ModelAttribute方法的返回值也放在隐含模型中【执行的是带有注解的@ModelAttribute】
                if (!implicitModel.containsAttribute(attrName)) {
                    implicitModel.addAttribute(attrName, attrValue);
                }
            }
        } catch (IllegalStateException var14) {
            throw new HandlerMethodInvocationException(handlerMethodToInvoke, var14);
        } catch (InvocationTargetException var15) {
            ReflectionUtils.rethrowException(var15.getTargetException());
            return null;
        }
    }

通过循环找到所有@ModelAttributeMethod注解标注的方法,然后确定ModelAttributeMethod方法执行时要使用的参数的值,通过调用 this.resolveHandlerArguments解析传过来的参数, this.resolveHandlerArguments源码如下:

private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
        Class[] paramTypes = handlerMethod.getParameterTypes();
        Object[] args = new Object[paramTypes.length];
 
        for(int i = 0; i < args.length; ++i) {
            MethodParameter methodParam = new MethodParameter(handlerMethod, i);
            methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
            GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
            String paramName = null;
            String headerName = null;
            boolean requestBodyFound = false;
            String cookieName = null;
            String pathVarName = null;
            String attrName = null;
            boolean required = false;
            String defaultValue = null;
            boolean validate = false;
            Object[] validationHints = null;
            int annotationsFound = 0;
            Annotation[] paramAnns = methodParam.getParameterAnnotations();
            Annotation[] var21 = paramAnns;
            int var22 = paramAnns.length;
             
            //循环找到所有标有注解的参数
            for(int var23 = 0; var23 < var22; ++var23) {
                Annotation paramAnn = var21[var23];
                if (RequestParam.class.isInstance(paramAnn)) {
                    RequestParam requestParam = (RequestParam)paramAnn;
                    paramName = requestParam.value();
                    required = requestParam.required();
                    defaultValue = this.parseDefaultValueAttribute(requestParam.defaultValue());
                    ++annotationsFound;
                } else if (RequestHeader.class.isInstance(paramAnn)) {
                    RequestHeader requestHeader = (RequestHeader)paramAnn;
                    headerName = requestHeader.value();
                    required = requestHeader.required();
                    defaultValue = this.parseDefaultValueAttribute(requestHeader.defaultValue());
                    ++annotationsFound;
                } else if (RequestBody.class.isInstance(paramAnn)) {
                    requestBodyFound = true;
                    ++annotationsFound;
                } else if (cookievalue.class.isInstance(paramAnn)) {
                    cookievalue cookievalue = (cookievalue)paramAnn;
                    cookieName = cookievalue.value();
                    required = cookievalue.required();
                    defaultValue = this.parseDefaultValueAttribute(cookievalue.defaultValue());
                    ++annotationsFound;
                } else if (PathVariable.class.isInstance(paramAnn)) {
                    PathVariable pathVar = (PathVariable)paramAnn;
                    pathVarName = pathVar.value();
                    ++annotationsFound;
                } else if (ModelAttribute.class.isInstance(paramAnn)) {
                    ModelAttribute attr = (ModelAttribute)paramAnn;
                    attrName = attr.value();
                    ++annotationsFound;
                } else if (Value.class.isInstance(paramAnn)) {
                    defaultValue = ((Value)paramAnn).value();
                } else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
                    validate = true;
                    Object value = AnnotationUtils.getValue(paramAnn);
                    validationHints = value instanceof Object[] ? (Object[])((Object[])value) : new Object[]{value};
                }
            }
 
            if (annotationsFound > 1) {
                throw new IllegalStateException("Handler parameter annotations are exclusive choices - do not specify more than one such annotation on the same parameter: " + handlerMethod);
            }
            
           //没有注解的参数
            if (annotationsFound == 0) {
               //解析普通的参数
                Object argValue = this.resolveCommonArgument(methodParam, webRequest);---解析标准参数【resolveCommonArgument】
                if (argValue != WebArgumentResolver.UNRESOLVED) {
                    args[i] = argValue;
                } else if (defaultValue != null) {
                    args[i] = this.resolveDefaultValue(defaultValue);
                } else {
                    Class paramType = methodParam.getParameterType();
                    if (!Model.class.isAssignableFrom(paramType) && !Map.class.isAssignableFrom(paramType)) {
                        if (SessionStatus.class.isAssignableFrom(paramType)) {
                            args[i] = this.sessionStatus;
                        } else if (HttpEntity.class.isAssignableFrom(paramType)) {
                            args[i] = this.resolveHttpEntityRequest(methodParam, webRequest);
                        } else {
                            if (Errors.class.isAssignableFrom(paramType)) {
                                throw new IllegalStateException("Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!");
                            }
 
                            if (BeanUtils.isSimpleProperty(paramType)) {
                                paramName = "";
                            } else {
                                attrName = "";
                            }
                        }
                    } else {
                        if (!paramType.isAssignableFrom(implicitModel.getClass())) {
                            throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " + "Model or Map but is not assignable from the actual model. You may need to switch " + "newer MVC infrastructure classes to use this argument.");
                        }
 
                        args[i] = implicitModel;
                    }
                }
            }
 
            if (paramName != null) {
                args[i] = this.resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
            } else if (headerName != null) {
                args[i] = this.resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
            } else if (requestBodyFound) {
                args[i] = this.resolveRequestBody(methodParam, webRequest, handler);
            } else if (cookieName != null) {
                args[i] = this.resolvecookievalue(cookieName, required, defaultValue, methodParam, webRequest, handler);
            } else if (pathVarName != null) {
                args[i] = this.resolvePathVariable(pathVarName, methodParam, webRequest, handler);
            } else if (attrName != null) {
                WebDataBinder binder = this.resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
                boolean assignBindingResult = args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]);
                if (binder.getTarget() != null) {
                    this.doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
                }
 
                args[i] = binder.getTarget();
                if (assignBindingResult) {
                    args[i + 1] = binder.getBindingResult();
                    ++i;
                }
 
                implicitModel.putAll(binder.getBindingResult().getModel());
            }
        }
 
        return args;
    }

首先从循环中找到所有标有注解的参数,然后对没有标注解的参数通过 this.resolveCommonArgument进行解析

protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
        if (this.customArgumentResolvers != null) {
            WebArgumentResolver[] var3 = this.customArgumentResolvers;
            int var4 = var3.length;
 
            for(int var5 = 0; var5 < var4; ++var5) {
                WebArgumentResolver argumentResolver = var3[var5];
                Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
                if (value != WebArgumentResolver.UNRESOLVED) {
                    return value;
                }
            }
        }
 
        Class paramType = methodParameter.getParameterType();
        Object value = this.resolveStandardArgument(paramType, webRequest);
        if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignablevalue(paramType, value)) {
            throw new IllegalStateException("Standard argument type [" + paramType.getName() + "] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) + "]. Consider declaring the argument type in a less specific fashion.");
        } else {
            return value;
        }
    }

2.判断是否是Model或者是Map旗下的,如果是将之前创建的隐含模型直接赋值给这个参数

5.如何确定方法每一个参数的值(方法括号中的参数)

1.标有注解的情况
保存哪个注解的详细信息,如果有ModelAttribute注解,就把标有注解的值交给attrName保存
2.没有标注解的情况
1.先看是否是普通参数(原生api),在看是否Model或者Map,如果是就传入隐含模型
2. 如果自定义类型的参数没有ModelAttribute注解
1.先看是否原生api,在看是否Model或者Map
2.再看是否其他类型的,比如SessionStatus,HttpEntity,Errors
3.再看是否简单属性,比如是否Integer,String,基本类型
4. 如果是paramName=“”;
5.attrName=“”
如果是自定义类型对象,最终会产生两个效果:
如果标注了ModelAttribute注解就给attrName赋值为这个注解的value值
如果没有标ModelAttribute注解就给attrName赋值为“”值

private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
        Class[] paramTypes = handlerMethod.getParameterTypes();
        Object[] args = new Object[paramTypes.length];
 
        for(int i = 0; i < args.length; ++i) {
            MethodParameter methodParam = new MethodParameter(handlerMethod, i);
            methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
            GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
            String paramName = null;
            String headerName = null;
            boolean requestBodyFound = false;
            String cookieName = null;
            String pathVarName = null;
            String attrName = null;
            boolean required = false;
            String defaultValue = null;
            boolean validate = false;
            Object[] validationHints = null;
            int annotationsFound = 0;
          //找到所有标了注解的参数
            Annotation[] paramAnns = methodParam.getParameterAnnotations();
            Annotation[] var21 = paramAnns;
            int var22 = paramAnns.length;
 
            for(int var23 = 0; var23 < var22; ++var23) {
                Annotation paramAnn = var21[var23];
               //判断是否是注解的值
                if (RequestParam.class.isInstance(paramAnn)) {
                    RequestParam requestParam = (RequestParam)paramAnn;
                    paramName = requestParam.value(); 将值赋值给paramName 
                    required = requestParam.required();
                    defaultValue = this.parseDefaultValueAttribute(requestParam.defaultValue());
                    ++annotationsFound;
                } else if (RequestHeader.class.isInstance(paramAnn)) {
                    RequestHeader requestHeader = (RequestHeader)paramAnn;
                    headerName = requestHeader.value();
                    required = requestHeader.required();
                    defaultValue = this.parseDefaultValueAttribute(requestHeader.defaultValue());
                    ++annotationsFound;
                } else if (RequestBody.class.isInstance(paramAnn)) {
                    requestBodyFound = true;
                    ++annotationsFound;
                } else if (cookievalue.class.isInstance(paramAnn)) {
                    cookievalue cookievalue = (cookievalue)paramAnn;
                    cookieName = cookievalue.value();
                    required = cookievalue.required();
                    defaultValue = this.parseDefaultValueAttribute(cookievalue.defaultValue());
                    ++annotationsFound;
                } else if (PathVariable.class.isInstance(paramAnn)) {
                    PathVariable pathVar = (PathVariable)paramAnn;
                    pathVarName = pathVar.value();
                    ++annotationsFound;
                } else if (ModelAttribute.class.isInstance(paramAnn)) {
                    ModelAttribute attr = (ModelAttribute)paramAnn;
                    attrName = attr.value();
                    ++annotationsFound;
                } else if (Value.class.isInstance(paramAnn)) {
                    defaultValue = ((Value)paramAnn).value();
                } else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
                    validate = true;
                    Object value = AnnotationUtils.getValue(paramAnn);
                    validationHints = value instanceof Object[] ? (Object[])((Object[])value) : new Object[]{value};
                }
            }
 
            if (annotationsFound > 1) {
                throw new IllegalStateException("Handler parameter annotations are exclusive choices - do not specify more than one such annotation on the same parameter: " + handlerMethod);
            }
          
           //解析普通参数,判断是否原生API,没有注解的参数
            if (annotationsFound == 0) {
                 //解析普通参数,判断是否原生API,没有注解的参数
                Object argValue = this.resolveCommonArgument(methodParam, webRequest);
                if (argValue != WebArgumentResolver.UNRESOLVED) {
                    args[i] = argValue;
                } else if (defaultValue != null) {
                    args[i] = this.resolveDefaultValue(defaultValue);
                } else {
                    Class paramType = methodParam.getParameterType();
                    if (!Model.class.isAssignableFrom(paramType) && !Map.class.isAssignableFrom(paramType)) {
                        if (SessionStatus.class.isAssignableFrom(paramType)) {
                            args[i] = this.sessionStatus;
                        } else if (HttpEntity.class.isAssignableFrom(paramType)) {
                            args[i] = this.resolveHttpEntityRequest(methodParam, webRequest);
                        } else {
                            if (Errors.class.isAssignableFrom(paramType)) {
                                throw new IllegalStateException("Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!");
                            }
 
                            if (BeanUtils.isSimpleProperty(paramType)) {
                                paramName = "";
                            } else {
                                attrName = "";
                            }
                        }
                    } else {
                        if (!paramType.isAssignableFrom(implicitModel.getClass())) {
                            throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " + "Model or Map but is not assignable from the actual model. You may need to switch " + "newer MVC infrastructure classes to use this argument.");
                        }
 
                        args[i] = implicitModel;
                    }
                }
            }
             //确定值的环节
            if (paramName != null) {
                args[i] = this.resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
            } else if (headerName != null) {
                args[i] = this.resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
            } else if (requestBodyFound) {
                args[i] = this.resolveRequestBody(methodParam, webRequest, handler);
            } else if (cookieName != null) {
                args[i] = this.resolvecookievalue(cookieName, required, defaultValue, methodParam, webRequest, handler);
            } else if (pathVarName != null) {
                args[i] = this.resolvePathVariable(pathVarName, methodParam, webRequest, handler);
           //确定自定义类型的参数,还要将请求中每一个参数的值赋值给这个对象(POJO)
            } else if (attrName != null) {
                WebDataBinder binder = this.resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
                boolean assignBindingResult = args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]);
                if (binder.getTarget() != null) {
                     //doBind方法将对象与请求中的对象 一 一绑定
                    this.doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
                }
 
                args[i] = binder.getTarget();
                if (assignBindingResult) {
                    args[i + 1] = binder.getBindingResult();
                    ++i;
                }
 
                implicitModel.putAll(binder.getBindingResult().getModel());
            }
        }
 
        return args;
    }

//确定自定义类型的参数,还要将请求中每一个参数的值赋值给这个对象(POJO)

private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam, ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
        String name = attrName;
        if ("".equals(attrName)) {
             //如果attrName是空串,就将参数类型的首字母小写作为值,User  user;name=user
            name = Conventions.getVariableNameForParameter(methodParam);
        }
 
        Class paramType = methodParam.getParameterType();
         //确定目标对象的值
        Object bindObject;
        if (implicitModel.containsKey(name)) {
            bindObject = implicitModel.get(name);
        } else if (this.methodResolver.isSessionAttribute(name, paramType)) {
            bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
            if (bindObject == null) {
                this.raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
            }
        } else {
             //利用反射创建对象
            bindObject = BeanUtils.instantiateClass(paramType);
        }
 
        WebDataBinder binder = this.createBinder(webRequest, bindObject, name);
        this.initBinder(handler, name, binder, webRequest);
        return binder;
    }

6.视图解析原理分析


SpringMvc视图解析:
1.方法执行后的返回值会作为页面地址参考,转发或者重定向到页面
2.视图解析器可能会进行页面 地址的拼串

1.任何方法的返回值,最终都会包装成ModelAndView对象

视图渲染执行: 来到页面的方法
this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

2.将域中的数据在页面显示,页面就是用来渲染模型数据的
3.调用this.render(mv, request, response); 渲染页面
4.View与ViewResolver:ViewResolver的作用是根据视图名(方法的返回值)得到view对象

protected View resolveViewName(String viewName, Map model, Locale locale, HttpServletRequest request) throws Exception {
        Iterator var5 = this.viewResolvers.iterator();
 
        View view;
         //遍历所有的ViewResolver
        do {
            if (!var5.hasNext()) {
                return null;
            }
 
            ViewResolver viewResolver = (ViewResolver)var5.next();
            //视图解析器,根据方法的返回值得到一个view对象
            view = viewResolver.resolveViewName(viewName, locale);
        } while(view == null);
 
        return view;
    }

resolveViewName:创建view对象,返回view对象

public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (!this.isCache()) {
            return this.createView(viewName, locale);
        } else {
            Object cacheKey = this.getCacheKey(viewName, locale);
            View view = (View)this.viewAccessCache.get(cacheKey);
            if (view == null) {
                synchronized(this.viewCreationCache) {
                    view = (View)this.viewCreationCache.get(cacheKey);
                    if (view == null) {
                        view = this.createView(viewName, locale);
                        if (view == null && this.cacheUnresolved) {
                            view = UNRESOLVED_VIEW;
                        }
 
                        if (view != null) {
                            this.viewAccessCache.put(cacheKey, view);
                            this.viewCreationCache.put(cacheKey, view);
                            if (this.logger.isTraceEnabled()) {
                                this.logger.trace("Cached view [" + cacheKey + "]");
                            }
                        }
                    }
                }
            }
           //如果没有前缀就使用父类默认创建一个view
            return view != UNRESOLVED_VIEW ? view : null;
        }
    }

视图解析器得到view对象的流程:
1、视图解析器得到View对象的流程就是,所有配置的视图解析器都来尝试根据视图名(返回值)得到View(视图)对象﹔如果能得到就返回,得不到就换下一个视图解析器
2、调用View对象的render方法;

一句话:
视图解析器只是为了得到视图对象;视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面视图对象才能真正的渲染视图;



7.总结

两件事:
1.运行流程简单版
2.确定方法每个参数的值:
标注解:保存注解的信息,最终得到这个注解对应的解析的值
没注解:
1.看是否是原生API
2.看是否Model或者Map等等
3.都不是,看是是否是简单类型:paramName
4.给attrName赋值:attrName(参数标了@ModelAuttrbute("")就是指定的,没标就是空串)
确定自定义类型参数:
1 ) 、attrName使用参数的类型首字母小写;或者使用之前@ModelAttribute("")的值
2)、先看隐含模型中有每个这个attrName作为key对应的值;如果有就从隐含模型中获取并赋值
3)、看是否是@SessionAttributes(value=“haha”);标注的 属性,如果是从session中拿; 如果拿不到就抛出异常
4)、不是@SessionAttributes标注的,利用反射创建一个对象﹔
5)、拿到之前创建好的对象,使用数据绑定器(WebDataBinder)将请求中的每个数据绑定到这个对象中

ModelAttrbute& SessionAttributes注解引发的异常:
@SessionAttributes(value= “haha”):在类上标了注解,但是在方法上没有对haha进行赋值,则会抛出找不到异常

@ModelAttrbute:标注的方法会提前运行并且把方法运行的运行结果放在隐含模型中
方的时候会使用一个key,如果@ModelAttrbute(value=“book”)指定了就用指定的book
如果没有指定就用返回值类型的首字母小写作为key,最好不要使用此方法,否则会创建一个新的属性:@ModelAttrbute基本不使用,了解即可

总结流程:

  • 1、所有请求,前端控制器(DispatcherServlet )收到请求,调用doDispatch进行处理
  • 2、根据HandlerMapping中保存的请求映射信息找到,处理当前请求的,处理器执行链(包含拦截器)
  • 3、根据当前处理器找到他的HandlerAdapter (适配器)
  • 4、拦截器的preHandle先执行
  • 5、适配器执行目标方法,并返回ModelAndView
    • 1 )、ModelAttribute注解标注的方法提前运行
    • 2 )、执行目标方法的时候(确定目标方法用的参数)
      • 1)、有注解
      • 2)、没注解:
        • 看是否Model、Map以及其他的
        • 如果是自定义类型:
          • 1 )、从隐含模型中看有没有,如果有就从隐含模型中拿
          • 2)、如果没有,再看是否SessionAttrbutes标注得属性,如果是从session中拿,如果拿不到会抛出异常
          • 3)、都不是,就会利用反射创建对象
    • 6、拦截器的postHandle执行
    • 7、处理结果;(页面渲染流程)
      • 1)、如果有异常使用异常解析器处理异常;处理完后还会返回ModelAndView
      • 2 )、调用render进行页面渲染
        • 1)、视图解析器根据视图名得到视图对象
        • 2 )、视图对象调用render方法;
      • 3 )、执行拦截器的afterCompletion ;

可以根据上面的步骤走一遍流程有助于加深理解!!!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644547.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号