SpringMVC-前端控制器源码分析

来源:互联网 发布:网络授课教师招聘 编辑:程序博客网 时间:2024/06/12 01:30

上篇文章中提到了关于springmvc的请求流程,大家 可以看到中心就是前端控制器DispatcherServlet的作用,今天小编来讲一下关于DispatcherServlet的源码分析过程。

第一步:前端控制器接收请求
DispatcherServlet中的jar包调用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 {            ModelAndView mv = null;            Exception dispatchException = null;            try {                processedRequest = checkMultipart(request);                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()) {                        String requestUri = urlPathHelper.getRequestUri(request);                        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 {                    // Actually invoke the handler.                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());                }                finally {                    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                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);                return;            }            // Clean up any resources used by a multipart request.            if (multipartRequestParsed) {                cleanupMultipart(processedRequest);            }        }    }

第二步:前端控制器调用处理器映射器查找Handler,通过url返回执行链

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;    }第三步:调用处理器适配器执行Handler,得到执行结果ModelAndViewmv = ha.handle(processedRequest, response, mappedHandler.getHandler());第四步:视图渲染,将Model数据填充到request域,查看下面的代码:protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {        // Determine locale for request and apply it to the response.        Locale locale = this.localeResolver.resolveLocale(request);        response.setLocale(locale);        View view;        if (mv.isReference()) {            // We need to resolve the view name.            view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);            if (view == null) {                throw new ServletException(                        "Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +                                getServletName() + "'");            }        }        else {            // No need to lookup: the ModelAndView object contains the actual View object.            view = mv.getView();            if (view == null) {                throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +                        "View object in servlet with name '" + getServletName() + "'");            }        }        // Delegate to the View object for rendering.        if (logger.isDebugEnabled()) {            logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");        }        view.render(mv.getModelInternal(), request, response);    }protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {        for (Map.Entry<String, Object> entry : model.entrySet()) {            String modelName = entry.getKey();            Object modelValue = entry.getValue();            if (modelValue != null) {                request.setAttribute(modelName, modelValue);                if (logger.isDebugEnabled()) {                    logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +                            "] to request in view with name '" + getBeanName() + "'");                }            }            else {                request.removeAttribute(modelName);                if (logger.isDebugEnabled()) {                    logger.debug("Removed model object '" + modelName +                            "' from request in view with name '" + getBeanName() + "'");                }            }        }    }

小结:
最后小编来总结一下springmvc前端控制器、处理器映射器、处理器适配器、视图解析器用法。
前端控制器配置:
第一种:*.action,访问以.action结尾由DispatcherServlet进行解析,解析源码见上面的分析。
第二种:/,访问的地址都是由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析。使用此种方式可以实现RESTful风格的url。

处理器映射器:
非注解处理器映射器(了解)
注解处理器映射器(掌握)
对标记@Controller类中标识有@requestMapping的方法进行映射,在@RequestMapping里边定义映射的
url。使用注解的映射器,不用再xml中配置url和Handler的映射关系。

处理器适配器:
非注解处理器适配器
注解处理器适配器
注解处理器适配器和注解的处理器映射器是配对使用。理解为不能使用非注解的处理器映射器进行映射。

这个mvc下的注解驱动可以代替下边的配置:

实际开发使用的是注解驱动

视图解析器:
可以配置前缀和后缀,来简约路径

0 0
原创粉丝点击