SpringMVC面试题总结「建议收藏」

SpringMVC面试题总结「建议收藏」前言:SpringMVC的面试题常见的也就那几种,本文我打算分为两个方向为大家介绍SpringMVC的面试题。第一部分将从源码的执行的角度分析SpringMVC(以后简称MVC)第二部分将从面试官常问的SpringMVC面试题取介绍SpringMVC源码介绍1.http://localhost:8000/hello这个路径的执行流程是怎么走的流程大致分析一下:首先会请求会进入前…

大家好,又见面了,我是你们的朋友全栈君。

前言:SpringMVC的面试题常见的也就那几种,本文我打算分为两个方向为大家介绍SpringMVC的面试题。

第一部分将从源码的执行的角度分析SpringMVC(以后简称MVC)

第二部分将从面试官常问的SpringMVC面试题取介绍

SpringMVC源码介绍

1.http://localhost:8000/hello这个路径的执行流程是怎么走的

流程大致分析一下:首先会请求会进入前端控制器的doService方法->调用doDispatch方法->调用handle方法->这个handle方法需要从RequestMappingHandlerAdapter的父类找到AbstractHandlerMethodAdapter里面的handle方法,这个方法又调用RequestMappingHandlerAdapter的handleInternal方法->调用this的invokeHandlerMethod->invokeAndHandle->invokeForRequest->doInvoke方法->doInvoke里面调用this.getBridgedMethod().invoke其中this.getBridgedMethod()这个就是controller里面的那个方法,这就利用了反射机制,这就是MVC的执行流程,期间经历了RequestMappingHandlerAdapter这个处理器适配器,ServletInvocableHandlerMethod Servlet处理控制方法,InvocableHandlerMethod执行方法反射这主要的三个类

下面将用截图代码分析MVC的执行流程

首先进入前端控制器的doservice方法,调用doDispatch方法

SpringMVC面试题总结「建议收藏」xa

下面看下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对象
                ModelAndView mv = null;
                Object dispatchException = null;
                //做检查
                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == 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()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }

                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
                    //这个就比较重要了,调用处理器适配器来处理
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }

                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

下面我们来看下mv = ha.handle(processedRequest, response, mappedHandler.getHandler());做了什么事吧

SpringMVC面试题总结「建议收藏」

说白了,这就是调用了RequestMappingHandlerAdapter里面的handleInternal方法

SpringMVC面试题总结「建议收藏」

可以看下invokeForRequest方法,最后调用doInvok方法

SpringMVC面试题总结「建议收藏」

第二种介绍:springmvc的流程图分析:

SpringMVC面试题总结「建议收藏」

1.用户请求进入前端控制器,调用doservice在调用doDispatch方法,调用getHandler方法,返回一个HandlerExecutionChain,里面包含一个你自己写的controller和mvc的拦截器,获得这个执行链mappedHandler之后,调用getHandlerAdapter(mappedHandler.getHandler())方法,获取适配器,这就是上图右半部分的分析,左半部分暂时未做分析

代码截图分析:

不要意思,纠正下错误,默认提供的映射器只有两种

SpringMVC面试题总结「建议收藏」

 

SpringMVC面试题总结「建议收藏」

拿到handler,来调用适配器的代码分析如下:

SpringMVC面试题总结「建议收藏」

后面的视图解析器部分以后再补充

2.映射路径的初始化源码分析

2.首先我们需要知道的是,我们写在controller里面的请求路径可是在应用程序加载启动时就被MVC加载好了的,存放到了一个Map里面。我们来分析下源码:

2.1在前端控制器中有一个initHandlerMappings方法,我们在这个方法打一个断点,程序在启动的时候就会进来

SpringMVC面试题总结「建议收藏」

2.2我们debug走到我们打断点的地方

SpringMVC面试题总结「建议收藏」

点开这些内容:

SpringMVC面试题总结「建议收藏」

我们会发现,MVC已经把对对应的关系放到了mappLookup中了,后续只需要取这个map里面取就行

3.MVC参数封装的原理分析(以最基础的类型参数封装为例)

前面的请求啥的都和前面分析的一样,我们直接看ServletInvocableHandlerMethod类里面的invoForRequest方法

SpringMVC面试题总结「建议收藏」

进去getMethodArgumentValues方法里面发现,主要是有一个argumentResove在起作用

SpringMVC面试题总结「建议收藏」

进入HandlerMethodArgumentResolverComposite类里面

SpringMVC面试题总结「建议收藏」

进入RequestParamMethodArgumentResolver这个类,通过servlet原始的封装getParamtermValues获取参数的值

SpringMVC面试题总结「建议收藏」

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/150799.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mac系统连接android电话

    mac系统连接android电话

    2022年1月6日
    61
  • java单例模式 三种_三种java单例模式概述

    java单例模式 三种_三种java单例模式概述在java语言的应用程序中,一个类Class只有一个实例存在,这是由java单例模式实现的。Java单例模式是一种常用的软件设计模式,java单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。下面就来介绍一下这三种java单例模式的相关内容。java单例模式是一种常见的设计模式,在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例,这也是…

    2022年7月25日
    8
  • vue数组拼接[通俗易懂]

    vue数组拼接[通俗易懂]例如目前有一组需求,后端传过来的数组里面包含经度,纬度两个属性。我们在前端展示的时候需要把他们放在一个表单直接上图

    2022年5月4日
    49
  • tomcat突然宕机问题解决方案

    tomcat突然宕机问题解决方案一.tomcat突然宕机时间2019年10月19号8点30分51秒,xxxx系统生产环境的92机器出现tomcat突然宕机问题。二.问题定位1.排查tomcat的启停日志。在文件tomcat/logs/localhost.xxxx.log,排查tomcat的启停日志正常。在宕机时刻,有关闭日志输出。2.使用history命令,查看系统的操作命令。发现使用‘./bi…

    2022年7月26日
    32
  • php js页面刷新,JS刷新页面方法总结

    php js页面刷新,JS刷新页面方法总结这次给大家带来JS刷新页面方法总结,JS刷新页面的注意事项有哪些,下面就是实战案例,一起来看一下。JS刷新当前页面的几种方法总结reload方法,该方法强迫浏览器刷新当前页面replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,你不能通过“前进”和“后退”来访问已经被替换的URL返回并刷新页面自动刷新页面的方法js刷新页面方法大全页面自…

    2022年7月14日
    15
  • RewriteCond指令格式

    RewriteCond指令格式RewriteCond指令格式语法:RewriteCondTestStringCondPattern[flags]RewriteCond指令定义一条规则条件。在一条RewriteRule指令前面可能会有一条或多条RewriteCond指令,只有当自身的模板(pattern)匹配成功且这些条件也满足时规则才被应用于当前URL处理。1、TestString是一个纯文本的字符串,除

    2022年6月13日
    27

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号