• springmvc源码分析


    我们都知道,使用springmvc要在web.xml中配置servlet:org.springframework.web.servlet.DispatcherServlet。那我们就从这个servlet开始,看看他的继承体系。

    集成体系:DispatcherServlet是继承自FrameworkServlet(抽象类),而FrameworkServlet继承自HttpServlet,这是他们的继承体系。

    springmvc处理请求思路:我们学习servlet的时候,请求会调用HttpServlet的service方法,service方法中有doGet,doPost方法,我们只要重写这些方法,就可以请求到我们自己编写的servlet中的doGet或doPost方法中。那么从这里可以看出,继承自HttpServlet的service方法就是处理请求的入口。那么springmvc就是根据这个思路来将请求扭转到自己的框架中的。

    springmvc具体处理:FrameworkServlet重写了HttpServlet的service方法,而DispatcherServlet又继承了FrameworkServlet,所以当用户请求时,会调用DispatcherServlet从父类继承下来的service方法,该方法在FrameworkServlet实现。具体源码:

    /**
         * Override the parent class implementation in order to intercept PATCH
         * requests.
         */
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            String method = request.getMethod();
            if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
                processRequest(request, response);
            }
            else {
                super.service(request, response);
            }
        }

    可以看出:如果请求的方法符合springmvc处理的,就自己处理,如果不符合,就交父类HttpServlet处理。那么我们来看看processRequest(request, response);是怎么处理的。其中有一个重要的代码(由于代码过长,没有复制):前面都是一些初始化参数。

    try {
                doService(request, response);
    }

    然后再来看看doService,该方法是在DispatcherServlet中实现的。里面有一句重要的代码:

    try {
                doDispatch(request, response);
         }

    庐山真面目开始慢慢出来了。那我们具体来看看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 {
                ModelAndView mv = null;
                Exception dispatchException = null;
    
                try {
                    processedRequest = checkMultipart(request);//判断是否是Multipart,处理文件上传
                    multipartRequestParsed = (processedRequest != request);
    
                    // Determine handler for the current request.
                    mappedHandler = getHandler(processedRequest, false);//得到处理器映射器
    
                    //如果不存在处理器映射器,则返回
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        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 (logger.isDebugEnabled()) {
                            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;
                    }
    
                    // Actually invoke the handler.
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//将真正的处理交给处理器处理mappedHandler.getHandler(),有不同的处理器适配器
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(request, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                }
                catch (Exception ex) {
                    dispatchException = ex;
                }
                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            }
            catch (Exception ex) {
                triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
            }
            catch (Error err) {
                triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
                    }
                }
            }
        }

    下面这个图是从别的博客下载过来的。http://www.cnblogs.com/sunniest/p/4555801.html

    这段代码很重要,所以全截了。

    首先判断请求是否是Multipart,处理文件上传的。

    springmvc中有两个重要的概念:处理器映射器和处理器适配器

        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
            return null;
        }

    DispatcherServlet维护了一个handlerMappings的list集合,存放处理器映射器的。可以通过配置文件配置,他也有默认配置。在DispatcherServlet下的

    DispatcherServlet.properties设置了一些属性。

    上面代码得到HandlerExecutionChain,通过HandlerExecutionChain得到HandlerAdapter

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            for (HandlerAdapter ha : this.handlerAdapters) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Testing handler adapter [" + ha + "]");
                }
                if (ha.supports(handler)) {
                    return ha;
                }
            }
            throw new ServletException("No adapter for handler [" + handler +
                    "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
        }
  • 相关阅读:
    vue table 中 列 加上 下划线和click 方法
    vue 比较好的学习文章
    Hive 以及mysql 中如何做except 数据操作
    oracle 日期维表 原始版本 带注解
    RMI 实现的rpc 远程过程调用 Java
    剑指offer20:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
    剑指offer19:按照从外向里以顺时针的顺序依次打印出每一个数字,4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
    模拟通讯录
    剑指offer17:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
    剑指offer16:输入两个单调递增的链表,合成后的链表满足单调不减规则。
  • 原文地址:https://www.cnblogs.com/hjy9420/p/5221991.html
Copyright © 2020-2023  润新知