14.spring-mvc源码

1.前端控制器的架构:

前端控制器在web.xml的配置:拦截请求,智能派发,并启动spring容器!
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

前端控制器:DispatcherServlet

1.前端控制器的架构?DispatcherServlet

前端控制器的架构如上图:

1.DispatcherServlet 继承于FrameworkServlet类

public class DispatcherServlet extends FrameworkServlet{
    
}

2.FrameworkServlet继承于HttpServletBean,HttpServletBean继承于HttpServlet,并重写了doget和dopost方法

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    //发现doGet/doPost均调用了本类中的processRequest方法
    protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processRequest(request, response);
    }
    protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processRequest(request, response);
    }
    //本类中的processRequest方法,在方法中又调用了本类的doService方法
    protected final void processRequest(HttpServletRequest request, HttpServletResponse response){
        ...
        this.doService(request, response);
        ...
    }
    //发现doservice方法是个抽象方法,具体的实现由其子类DispatcherServlet 实现,即具体的处理在DispatcherServlet 的doservice方法中
    protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}

3.DispatcherServlet 的doservice方法

public class DispatcherServlet extends FrameworkServlet{
   protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
       ...
       //调用了本类的doDispatch来处理请求
       this.doDispatch(request, response);
       ...
   }
   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 {
                    //1.检查请求是否是文件上传请求
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    
                    //2.根据当前的请求地址查看哪个类能来处理
                    mappedHandler = this.getHandler(processedRequest);
                    
                    //3.如果没有找到哪个处理器(控制器)可以处理该请求,就会抛出异常!,或报404
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                    
                    //4.拿到能执行这个类的所有方法的适配器(相当于反射工具,最终通过该适配器执行方法ha=AnnotationMethodHandlerAdapter)
                    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 {
                        //执行目标方法:处理器(控制器的方法被执行)  处理器:handle  控制器:controler
                        //5.适配器执行目标方法,将目标方法执行完成后的返回值作为视图名,设置保存在ModealAndView中
                        //目标方法无论怎么执行,不管返回值是String/Modeal/ModealMap,其底层适配器都会将其将目标方法的执行结果封装到ModelAndView中
                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    } finally {
                        if (asyncManager.isConcurrentHandlingStarted()) {
                            return;
                        }
                    }
                    //6.如果没有视图名称,即目标方法没有返回视图名,则设置一个默认的视图名称
                    this.applyDefaultViewName(request, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var28) {
                    dispatchException = var28;
                }
                //转发到页面
                //7.根据方法最终执行后的封装的ModelAndView,转发到对应的页面,而且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()方法进行处理
    2.1. mappedHandler =this.getHandler(processedRequest);根据当前的请求地址找到能处理这个请求的目标处理器类(处理器)
      根据当前请求在handlerMapping中查找这个请求的映射信息,获取目标处理类
    2.2.HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()):根据当前处理器类获取能执行这个处理器方法的适配器
      根据当前处理器类,找到当前类的HandlerAdapter(适配器-->反射工具,用于最终处理目标方法)
    2.3.使用刚才的适配器(AnnotationMethodHandlerAdapter)执行目标方法
    2.4目标方法执行后会返回一个ModelAndView对象
    2.5根据ModelAndView的信息转发到具体的页面,并在请求域中拿到ModelAndView中的模型数据

 

1.getHandler细节:获取请求处理器,怎么根据当前请求找到哪个类进行处理

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //通过下图知道:handlerMappings有两个属性值:BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping
    //BeanNameUrlHandlerMapping:基于配置的
    //DefaultAnnotationHandlerMapping:基于注解的@RequestMapping
    //每次请求过来都会遍历BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping,拿到处理请求的处理类
    //如果配置和注解标注了同一个方法,配置有效
    Iterator var2 = this.handlerMappings.iterator();
    HandlerExecutionChain handler;
    do {
        if (!var2.hasNext()) {
            return null;
        }
        HandlerMapping hm = (HandlerMapping)var2.next();
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
        }
        handler = hm.getHandler(request);
    } while(handler == null);
    return handler;
}
handlerMap如何有路径和处理类的对应关系:IOC创建每个Controler对象时,会扫描@RequestMapping,查看处理器能够处理什么请求,并保存在handlerMappings中的handlerMap中,下一次请求过来就直接看hadlermapping中有这个请求映射信息就行了

2.getHandlerAdapter拿到执行方法的适配器:

如何找到目标处理器类的适配器,要拿到适配器才能执行目标方法
适配器可以理解成是一种反射工具,使用第三个适配器
AnnotationMethodHandlerAdapter:能解析注解的适配器

 

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    Iterator var2 = this.handlerAdapters.iterator();
    HandlerAdapter ha;
    do {
        if (!var2.hasNext()) {
            throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
        }
        ha = (HandlerAdapter)var2.next();
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler adapter [" + ha + "]");
        }
    } while(!ha.supports(handler));
    return ha;
}
handlerAdapters的最后一项AnnotationMethodHandlerAdapter,会判断处理器中是否有@requesMapping标注而加载到容器中的方法,有方法就可以执行

ha.supports(handler)的细节:
    前两项的细节均是:
        1.
        public boolean supports(Object handler) {
            return handler instanceof HttpRequestHandler;
        }
        2.
        public boolean supports(Object handler) {
            return handler instanceof Controller;
        }
    最后一项:AnnotationMethodHandlerAdapter会判断处理器是否有带@requesMapping的方法
    public final boolean hasHandlerMethods() {
        return !this.handlerMethods.isEmpty();
    }
handlerAdapters和handlerMappings是何时有值的呢,在上述在中,查找处理器遍历handlerMappings,查找适配器遍历handlerAdapters

DispatcherServlet中有以下9个引用类型变量:springmvc的九大组件
springmvc在工作的时候,关键位置都是由这些组件完成

//1.文件上传解析器
private MultipartResolver multipartResolver;
//2.国际化
private LocaleResolver localeResolver;
//3.主题解析器:强大的主题效果更换
private ThemeResolver themeResolver;
//4.handler映射信息:请求路径和处理类的对应关系
private List<HandlerMapping> handlerMappings;------->处理器
//5.handler的适配器
private List<HandlerAdapter> handlerAdapters;------->适配器
//6.springmcvc强大的异常解析功能:异常解析器
private List<HandlerExceptionResolver> handlerExceptionResolvers;
//7.不用
private RequestToViewNameTranslator viewNameTranslator;
//8.FlashMap+Manager,springmvcc在运行中允许重定向携带数据。将数据保存在session中
private FlashMapManager flashMapManager;
//9.视图解析器
private List<ViewResolver> viewResolvers;
,
以上的九大组件均是接口,将组件做成接口的好处?接口就是规范,提供了强大的扩展性

九大组件初始化的地方

DispatcherServlet中:
springmvc在启动时会调用onRefresh方法,initStrategies方法中有九大组件的初始化
protected void onRefresh(ApplicationContext context) {
    this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
    this.initMultipartResolver(context);
    this.initLocaleResolver(context);
    this.initThemeResolver(context);
    this.initHandlerMappings(context);
    this.initHandlerAdapters(context);
    this.initHandlerExceptionResolvers(context);
    this.initRequestToViewNameTranslator(context);
    this.initViewResolvers(context);
    this.initFlashMapManager(context);
}

1.handlerMappings 的初始化

可以在web.xml中更改DispatcherServlet某些属性的默认值,但尽量不改,除非特别熟悉该属性的作用
    public class DispatcherServlet extends FrameworkServlet {
        ...
        private boolean detectAllHandlerMappings = true;
        ...
    }
在web.xml中可以更改其默认值:
    <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>detectAllHandlerMappings</param-name>------------->更改其默认值时false
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    if (this.detectAllHandlerMappings) {
        //1.使用bean工厂,按照类型查找所有的HandlerMapping组件
        Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList(matchingBeans.values());
            OrderComparator.sort(this.handlerMappings);
        }
    } else {
        try {
            //2.如果找不到,按照id去容器中查找HandlerMapping组件
            HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        } catch (NoSuchBeanDefinitionException var3) {
        }
    }
    //3.如果上述的均没有找到HandlerMapping组件,就使用默认配置
    if (this.handlerMappings == null) {
        this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
        }
    }
}
组件的初始化:
    有些组件在容器中是按照类型查找的,有些组件是按照id查找的
    去容器中找这个组件,如果没有就使用默认配置

ha.handle()执行目标方法

spring底层是通过反射来执行目标方法的,但是若让我们写method.invoke(this,args)最难确定的就是参数,因为spring对参数要求较低
例如下述请求包含了四种请求参数
@RequestMapping("/hello")
public String updateBook(
        @RequestParam(value = "bookName") String bookName,
        Map<String, Object> map,
        HttpServletRequest request,
        @ModelAttribute("hhh") Book book){
            
}
执行目标方法细节

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //1.判断目标处理器类中是否包含@SessionAttributes注解
    ....
    //2.执行目标方法
    return this.invokeHandlerMethod(request, response, handler);
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     //1.拿到方法的解析器
     AnnotationMethodHandlerAdapter.ServletHandlerMethodResolver methodResolver = this.getMethodResolver(handler);
     //2.方法解析器根据当前路径拿到真正的目标方法
     Method handlerMethod = methodResolver.resolveHandlerMethod(request);
     //3.创建一个方法执行器
    AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker methodInvoker = new AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker(methodResolver);
    //4.封装原生的request, response对象
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    //5.创建一个BindingAwareModelMap:由之前可知,在带@RequestMapping目标方法中传入的map/modelMap,最终的类型都是BindingAwareModelMap,这就是原因
    //创建了一个隐含的模型
    ExtendedModelMap implicitModel = new BindingAwareModelMap();
    
    //6.真正的执行目标方法
    //目标方法利用反射执行期间,通过反射确定参数值,提前执行@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;
}


其中:具体的执行代码如下:
public final Object invokeHandlerMethod(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
    //1.获取执行的目标方法
    Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
    try {
        boolean debug = logger.isDebugEnabled();
        
        //2.获取带@SessionAttribute注解的方法
        Iterator var7 = this.methodResolver.getActualSessionAttributeNames().iterator();
        while(var7.hasNext()) {
            String attrName = (String)var7.next();
            Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
            if (attrValue != null) {
                //3.若session中有值,会将其存储在上面创建的隐含模型中:ExtendedModelMap implicitModel = new BindingAwareModelMap();
                implicitModel.addAttribute(attrName, attrValue);
            }
        }
        
        //4.获取@ModelAttribute的方法
        var7 = this.methodResolver.getModelAttributeMethods().iterator();
        while(true) {
            Object[] args;
            String attrName;
            Method attributeMethodToInvoke;
            do {
                if (!var7.hasNext()) {
                    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);
                }
                //5.获取到需要执行的@ModelAttribute的方法
                Method attributeMethod = (Method)var7.next();
                attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
                //5.重要:获取执行方法的参数---------------------------->获取执行目标方法的参数
                args = this.resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
                if (debug) {
                    logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
                }
                //6.获取带@ModelAttribute(value="")的value值
                attrName = ((ModelAttribute)AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class)).value();
            } while(!"".equals(attrName) && implicitModel.containsAttribute(attrName));

            ReflectionUtils.makeAccessible(attributeMethodToInvoke);
             //6.执行目标方法
            Object attrValue = attributeMethodToInvoke.invoke(handler, args);
            //7.这里会获取到@ModelAttribute(value="")的value值
            /**
             *   1.如果带@ModelAttribute(value="abc")有值:attrName="abc"
             *   @ModelAttribute(value = "abc")
             *    public void selectBookByBookname(Map <String,Object> map,Book book,@RequestParam(value = "bookName") String bookName){
             *         ...   
             *    }
             *   2.没标value值,attrName="";
             */
            if ("".equals(attrName)) {
                Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
                //8. @ModelAttribute没标value时,attrName 是返回值的首字母小写,若为void,attrName="void",若返回值是Book,attrName="book"
                attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
            }
            //9.判断隐含模型中是否包含:attrName ="void",不包含就将其放入在隐含模型中:void=null
            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;
    }
【分析源码得知】
  @ModelAttribute标签的另外一个作用:
  可以将方法执行返回返回值按照方法上@ModelAttribute("abc")指定的key放到隐含模型中
  没有这个key,就按方法返回值的小写
确定目标方法的参数个数和类型:
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
    //1.获取参数类型,返回数组
    Class<?>[] paramTypes = handlerMethod.getParameterTypes();
    //2.创建一个和参数长度相同的数组
    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;
        //找到目标方法的所有注解,例如@RequestParam,如果有注解就解析并保存信息
        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 value = this.resolveStandardArgument(paramType, webRequest);解析标准参数
            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();
                //判断参数是否是Model和Map旗下的,如果不是就将创建的对象:bindingAwareModelMap赋值给参数
                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.");
                    }
                    //将隐含对象BindingAwareModelMap赋值给参数值!
                    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;
}
在解析普通参数(resolveCommonArgument)方法中,会先调用自定义参数解析器(customArgumentResolvers)->无用,然后会调用标准参数解析器(resolveStandardArgument)->判断是否是原生api
标准参数解析器细节如下:发现其是判断参数是否为servlet原生的参数:如request /response 等
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
    HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
    HttpServletResponse response = (HttpServletResponse)webRequest.getNativeResponse(HttpServletResponse.class);
    Object nativeResponse;
    if (!ServletRequest.class.isAssignableFrom(parameterType) && !MultipartRequest.class.isAssignableFrom(parameterType)) {
        if (ServletResponse.class.isAssignableFrom(parameterType)) {
            this.responseArgumentUsed = true;
            nativeResponse = webRequest.getNativeResponse(parameterType);
            if (nativeResponse == null) {
                throw new IllegalStateException("Current response is not of type [" + parameterType.getName() + "]: " + response);
            } else {
                return nativeResponse;
            }
        } else if (HttpSession.class.isAssignableFrom(parameterType)) {
            return request.getSession();
        } else if (Principal.class.isAssignableFrom(parameterType)) {
            return request.getUserPrincipal();
        } else if (Locale.class.equals(parameterType)) {
            return RequestContextUtils.getLocale(request);
        } else if (InputStream.class.isAssignableFrom(parameterType)) {
            return request.getInputStream();
        } else if (Reader.class.isAssignableFrom(parameterType)) {
            return request.getReader();
        } else if (OutputStream.class.isAssignableFrom(parameterType)) {
            this.responseArgumentUsed = true;
            return response.getOutputStream();
        } else if (Writer.class.isAssignableFrom(parameterType)) {
            this.responseArgumentUsed = true;
            return response.getWriter();
        } else {
            return super.resolveStandardArgument(parameterType, webRequest);
        }
    } else {
        nativeResponse = webRequest.getNativeRequest(parameterType);
        if (nativeResponse == null) {
            throw new IllegalStateException("Current request is not of type [" + parameterType.getName() + "]: " + request);
        } else {
            return nativeResponse;
        }
    }
}

总结:

运行两件事:
1.运行流程简单版
2.确定方法上每个参数值
2.1标了注解:保存注解信息,最终得到这个注解应该对应解析的值
2.2没标注解:
2.2.1看是否是原生的api
2.2.2看是否是Model或者Map,xxxx
2.2.3都不是,看是否是简单类型
2.2.4给attrName赋值;attename(参数标注了@ModelAttribute(""))就是指定的,没标就是""
确定自定义类型参数:
1.attrName用参数类型首字母小写,或者用之前@ModelAttribute("")的值,
2.确定隐含模型中每个attrname作为key的值;如果有就从隐含模型中拿值
3.看是否是@SessionAttribute(value="hhh")标注的属性,如果是就从session中拿,如果拿不到就会抛异常!
4.如果不是@SessionAttribute标注的,利用反射创建一个对象
2.2.5.拿到之前创建好的对象,使用数据绑定器(webDataBinder)将请求中的每个数据绑定到这个对象中

posted @ 2022-05-08 22:00  努力的达子  阅读(56)  评论(0编辑  收藏  举报