springmvc小计

2020-06-18  本文已影响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也是在这时候初始化的
    
    
上一篇下一篇

猜你喜欢

热点阅读