美文网首页
springmvc小计

springmvc小计

作者: 可靠的千秋 | 来源:发表于2020-06-18 08:09 被阅读0次
    近日在复习SpringMVC,故整理一下笔记
    SpringMVC是在Spring框架内置的MVC的实现,其本质是对Servlet的一个封装。
    MVC(Model-View-Controller,模型-视图-控制器)指把页面、后台的交付分成3层来组成,是一种解决页面代码(视图代码)和后台代码分离的设计思想。
    
    SpringMVC原理
    1,在web.xml中配置过ContextLoaderListener监听器,监听容器的启动
    2,监听器监听容器启动,加载配置文件,初始化对象存在容器中
    3,用户发起请求,到HttpServlet,调doPost/doGet/doPut/doDelete,调用DispatcherServlet的doDispatch方法,进行具体请求的处理
    4,处理完成,返回一个ModelAndView,视图解析器进行渲染,返回前端。
    
    核心方法doDispatch
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        //handler执行链
        HandlerExecutionChain mappedHandler = null;
        //是不是多部件请求-文件上传
        boolean multipartRequestParsed = false;
        //异步管理器
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
    
            try {
                //是不是文件上传
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);
    
                // Determine handler for the current request.
                //根据请求,找到能处理当前请求的执行链
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {
                    //404
                    noHandlerFound(processedRequest, response);
                    return;
                }
    
                // Determine handler adapter for the current request.
                //获得处理请求适配器
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
    
                if (!mappedHandler.applyPreHandle(processedRequest, response)) { //拦截器
                    return;
                }
    
                // Actually invoke the handler. 实际处理请求
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
                //结构视图对象处理
                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv); //拦截器
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            //跳转页面渲染视图
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }
    
    这边直接贴出代码,其核心是**mv = ha.handle(processedRequest, response, mappedHandler.getHandler());**这行来执行真正的请求。
    1,实际上里面是通过找到Method的对象,进行的反射调用。那是怎么找到Method的呢,是因为HandlerAdapter
    HandlerAdapter
        我们来看HandlerAdapter,他有好几个实现类
    
        ![下载](https://note.youdao.com/yws/res/5751/F2E4DCC6847D4F419445692639EA797F)
        AbstractHandlerMethodAdapter的handle调用handleInternal,然后调用RequestMappingHandlerAdapter的invokeHandlerMethod方法->invocableMethod.invokeAndHandle(webRequest, mavContainer) -> invokeForRequest -> doInvoke -> getBridgedMethod().invoke(getBean(), args) 进行具体执行,其实就是解析参数,进行反射调用。
    2,我们再来看getHandler(processedRequest);获得具体的处理器映射器
        @Nullable
        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            if (this.handlerMappings != null) {
                for (HandlerMapping mapping : this.handlerMappings) {
                    HandlerExecutionChain handler = mapping.getHandler(request);
                    if (handler != null) {
                        return handler;
                    }
                }
            }
            return null;
        }
        其执行的是getHandler,循环调用mapping.getHandler(request);而getHandler内部调用getHandlerExecutionChain(handler, request);做一个url的匹配,返回一个HandlerExecutionChain执行链
        我们来看mapping,他是一个HandlerMapping类型的集合,HandlerMapping的核心实现RequestMappingHandlerMapping类,用来映射请求映射的一个关系对象,它的getMappingForMethod方法在bean对象启动时加载,返回一个RequestMappingInfo对象,缓存方法请求的信息,也就是项目启动时,会将方法上的@RequestMapping会被转换为RequestMappingInfo对象,isHandler方法用于过滤是否是被Controller和RequestMapping修饰
        项目启动之后,Spring可以获取到容器中的所有Bean对象。而RequestMappingHandlerMapping是@RequestMapping标签的处理器映射器。
        
        而为什么mapping会有数据呢,他其实是DispatcherServlet九大组件之一,在Servlet启动的时候,会调用init,然后向下执行onRefresh->initStrategies(),从ApplicationContext里初始化9大组件HandlerAdapters也是在这时候初始化的
        
        
    

    相关文章

      网友评论

          本文标题:springmvc小计

          本文链接:https://www.haomeiwen.com/subject/yisyxktx.html