zoukankan      html  css  js  c++  java
  • SpringMVC源码分析

    SpringMVC源码分析

    流程分析

    1.初始化

    Servlet接口:

    public interface Servlet {
        //1.init(),初始化servlet对象,完成一些初始化工作。它是由servlet容器控制的,该方法只能被调用一次。
        void init(ServletConfig var1) throws ServletException;
    
        ServletConfig getServletConfig();
         //2.service(),接受客户端请求对象,执行业务操作,利用响应对象响应客户端请求。
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
        String getServletInfo();
        //3.destroy(),当容器监测到一个servlet从服务中被移除时,容器调用该方法,释放资源。
        void destroy();
    }
    

    GenericServlet:

    public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    
    
        public void init(ServletConfig config) throws ServletException {
                this.config = config;
                this.init();
            }
    
        public void init() throws ServletException {
        }
    
            public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
        
        public void destroy() {
        }
      
     }   
    

    HttpServlet

    public abstract class HttpServlet extends GenericServlet {
    
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String method = req.getMethod();
            long lastModified;
            if (method.equals("GET")) {
                lastModified = this.getLastModified(req);
                if (lastModified == -1L) {
                    this.doGet(req, resp);
                } else {
                    long ifModifiedSince;
                    try {
                        ifModifiedSince = req.getDateHeader("If-Modified-Since");
                    } catch (IllegalArgumentException var9) {
                        ifModifiedSince = -1L;
                    }
    
                    if (ifModifiedSince < lastModified / 1000L * 1000L) {
                        this.maybeSetLastModified(resp, lastModified);
                        this.doGet(req, resp);
                    } else {
                        resp.setStatus(304);
                    }
                }
            } else if (method.equals("HEAD")) {
                lastModified = this.getLastModified(req);
                this.maybeSetLastModified(resp, lastModified);
                this.doHead(req, resp);
            } else if (method.equals("POST")) {
                this.doPost(req, resp);
            } else if (method.equals("PUT")) {
                this.doPut(req, resp);
            } else if (method.equals("DELETE")) {
                this.doDelete(req, resp);
            } else if (method.equals("OPTIONS")) {
                this.doOptions(req, resp);
            } else if (method.equals("TRACE")) {
                this.doTrace(req, resp);
            } else {
                String errMsg = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[]{method};
                errMsg = MessageFormat.format(errMsg, errArgs);
                resp.sendError(501, errMsg);
            }
    
        }
    
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            HttpServletRequest request;
            HttpServletResponse response;
            try {
                request = (HttpServletRequest)req;
                response = (HttpServletResponse)res;
            } catch (ClassCastException var6) {
                throw new ServletException(lStrings.getString("http.non_http"));
            }
    
            this.service(request, response);
        }
    }
    

    HttpServletBean

    public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
        
        public final void init() throws ServletException {
            // 获取在web.xml配置的初始化参数<init-param>,并将其设置到DispatcherServlet中
            PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
            
            if (!pvs.isEmpty()) {
                try {
                     // 使用BeanWrapper构造DispatcherServlet
                    BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                    ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
                    bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
                    this.initBeanWrapper(bw);
                    
                    // 设置DispatcherServlet属性
                    bw.setPropertyValues(pvs, true);
                } catch (BeansException var4) {
                    if (this.logger.isErrorEnabled()) {
                        this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
                    }
    
                    throw var4;
                }
            }
    
            // 设置DispatcherServlet属性
            this.initServletBean();
        }
    

    FrameworkServlet

    public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    
    
     protected final void initServletBean() throws ServletException {
            this.getServletContext().log("Initializing Spring " + this.getClass().getSimpleName() + " '" + this.getServletName() + "'");
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Initializing Servlet '" + this.getServletName() + "'");
            }
    
            long startTime = System.currentTimeMillis();
    
            try {
                
                //初始化WebApplicationContext属性
                this.webApplicationContext = this.initWebApplicationContext();
                this.initFrameworkServlet();
            } catch (RuntimeException | ServletException var4) {
                this.logger.error("Context initialization failed", var4);
                throw var4;
            }
    
            if (this.logger.isDebugEnabled()) {
                String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data";
                this.logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value);
            }
    
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
            }
    
        }
        
    

    initWebApplicationContext()

    protected WebApplicationContext initWebApplicationContext() {
        // 获取root WebApplicationContext,即web.xml中配置的listener(ContextLoaderListener)
            WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
            WebApplicationContext wac = null;
        
         // 判断容器是否由编程式传入(即是否已经存在了容器实例),存在的话直接赋值给wac,给springMVC容器设置父容器
        // 最后调用刷新函数configureAndRefreshWebApplicationContext(wac),作用是把Spring MVC配置文件的配置信息加载到容器中去
            if (this.webApplicationContext != null) {
                
                // context上下文在构造是注入
                wac = this.webApplicationContext;
                if (wac instanceof ConfigurableWebApplicationContext) {
                    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
                    
                    // context没有被refreshed,提供一些诸如设置父context、设置应用context id等服务
                    if (!cwac.isActive()) {
                        if (cwac.getParent() == null) {
                            cwac.setParent(rootContext);
                        }
    
                        this.configureAndRefreshWebApplicationContext(cwac);
                    }
                }
            }
    
           // No context instance was injected at construction time -> see if one
          // has been registered in the servlet context. If one exists, it is assumed
          // that the parent context (if any) has already been set and that the
          // user has performed any initialization such as setting the context id
        // 在ServletContext中寻找是否有Spring MVC容器,初次运行是没有的,Spring MVC初始化完毕ServletContext就有了Spring MVC容器
            if (wac == null) {
                wac = this.findWebApplicationContext();
            }
        
          // No context instance is defined for this servlet -> create a local one
          // 创建web上下文对象
          // 当wac既没有没被编程式注册到容器中的,也没在ServletContext找得到,此时就要新建一个Spring MVC容器
            if (wac == null) {
                wac = this.createWebApplicationContext(rootContext);
            }
    
          // Either the context is not a ConfigurableApplicationContext with refresh
          // support or the context injected at construction time had already been
          // refreshed -> trigger initial onRefresh manually here.
          // 执行DispatcherServlet的实现 初始化springmvc九大组件
    
            if (!this.refreshEventReceived) {
                synchronized(this.onRefreshMonitor) {
                    this.onRefresh(wac);
                }
            }
    
        // 将Spring MVC容器存放到ServletContext中去,方便下次取出来
            if (this.publishContext) {
                String attrName = this.getServletContextAttributeName();
                this.getServletContext().setAttribute(attrName, wac);
            }
    
            return wac;
        }
    
    

    createWebApplicationContext()

    protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
        Class<?> contextClass = this.getContextClass();
        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
            throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
        } else {
            
            // 实例化容器
            // 通过反射实例化web上下文对象
            ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
            // 设置容器环境
        wac.setEnvironment(getEnvironment());
        // 设置父容器
        wac.setParent(parent);
        // 加载Spring MVC的配置信息,如:bean注入、注解、扫描等等
        String configLocation = getContextConfigLocation();
        if (configLocation != null) {
            wac.setConfigLocation(configLocation);
        }
        // 刷新容器,根据Spring MVC配置文件完成初始化操作
            this.configureAndRefreshWebApplicationContext(wac);
            return wac;
    }
    

    configureAndRefreshWebApplicationContext()

    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
            if (this.contextId != null) {
                wac.setId(this.contextId);
            } else {
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(this.getServletContext().getContextPath()) + '/' + this.getServletName());
            }
        }
    
        wac.setServletContext(this.getServletContext());
        wac.setServletConfig(this.getServletConfig());
        wac.setNamespace(this.getNamespace());
        wac.addApplicationListener(new SourceFilteringListener(wac, new FrameworkServlet.ContextRefreshListener()));
        
        // The wac environment's #initPropertySources will be called in any case when the context
       // is refreshed; do it eagerly here to ensure servlet property sources are in place for
       // use in any post-processing or initialization that occurs below prior to #refresh
        ConfigurableEnvironment env = wac.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment)env).initPropertySources(this.getServletContext(), this.getServletConfig());
        }
    
        this.postProcessWebApplicationContext(wac);
        this.applyInitializers(wac);
        
        // 刷新web上下文 refresh方法可查看IoC容器初始化过程
        wac.refresh();
    }
    

    refresh()

    void refresh() throws BeansException, IllegalStateException;
    

    DispatcherServlet

    onRefresh

    public class DispatcherServlet extends FrameworkServlet {
    
        protected void onRefresh(ApplicationContext context) {
                this.initStrategies(context);
            }
       
    

    initStrategies()

      protected void initStrategies(ApplicationContext context) {
            // 初始化文件上传处理
       initMultipartResolver(context);
       // 初始化本地化处理
       initLocaleResolver(context);
       // 初始化主题处理
       initThemeResolver(context);
       // 初始化处理器映射器(用来保存controller中配置的RequestMapping与Method对应关系)
       initHandlerMappings(context);
       // 初始化处理器适配器(用来动态匹配Method参数 包括类转换 动态赋值)
       initHandlerAdapters(context);
       // 初始化处理器异常处理
       initHandlerExceptionResolvers(context);
       // 初始化请求至视图名转换
       initRequestToViewNameTranslator(context);
       // 初始化视图解析器
       initViewResolvers(context);
       // 初始化flash映射管理器
       initFlashMapManager(context);
        }
    

    2.提供服务——执行过程解析

    当一个 post/get 请求进来后,会调用 FrameworkServletdoPost/doGet 方法,这里以 post 请求为例

    FrameworkServlet

    doPost()

    protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.processRequest(request, response);
        }
    

    processRequest()

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            long startTime = System.currentTimeMillis();
            Throwable failureCause = null;
            LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
            LocaleContext localeContext = this.buildLocaleContext(request);
            RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
            asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
            this.initContextHolders(request, localeContext, requestAttributes);
    
            try {
                
                 // 执行请求
                this.doService(request, response);
            } catch (IOException | ServletException var16) {
                failureCause = var16;
                throw var16;
            } catch (Throwable var17) {
                failureCause = var17;
                throw new NestedServletException("Request processing failed", var17);
            } finally {
                this.resetContextHolders(request, previousLocaleContext, previousAttributes);
                if (requestAttributes != null) {
                    requestAttributes.requestCompleted();
                }
    
                this.logResult(request, response, (Throwable)failureCause, asyncManager);
                this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
            }
    
        }
    

    DispatcherServlet

    doService()

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
            this.logRequest(request);
        
        // Keep a snapshot of the request attributes in case of an include,
       // to be able to restore the original attributes after the include.
            Map<String, Object> attributesSnapshot = null;
            if (WebUtils.isIncludeRequest(request)) {
                attributesSnapshot = new HashMap();
                Enumeration attrNames = request.getAttributeNames();
    
                label95:
                while(true) {
                    String attrName;
                    do {
                        if (!attrNames.hasMoreElements()) {
                            break label95;
                        }
    
                        attrName = (String)attrNames.nextElement();
                    } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
    
                    attributesSnapshot.put(attrName, request.getAttribute(attrName));
                }
            }
        
           // Make framework objects available to handlers and view objects.
            request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
            request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
            request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
            request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
            if (this.flashMapManager != null) {
                FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
                if (inputFlashMap != null) {
                    request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
                }
    
                request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
                request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
            }
    
            try {
                this.doDispatch(request, response);
            } finally {
                
                 // Restore the original attribute snapshot, in case of an include.
                if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                    this.restoreAttributesAfterInclude(request, attributesSnapshot);
                }
    
            }
    
        }
    

    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 mv = null;
                    Object dispatchException = null;
    
                    try {
                        
                        // 如果是MultipartContent类型则转换为MultiHttpServletRequest类型的request
                        processedRequest = this.checkMultipart(request);
                        multipartRequestParsed = processedRequest != request;
                        
                        // 根据request寻找对应的handler
                        mappedHandler = this.getHandler(processedRequest);
                        if (mappedHandler == null) {
                            this.noHandlerFound(processedRequest, response);
                            return;	
                        }
                        
                        // 根据处理器获取handler适配器
                        HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                        
                        // 如果当前handler支持last-modified头处理
                        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;
                            }
                        }
                        
                        // 拦截器postHandle方法处理
                        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                            return;
                        }
    
                         // Actually invoke the handler.
                         // 处理器处理请求 返回结果试图对象
                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                        if (asyncManager.isConcurrentHandlingStarted()) {
                            return;
                        }
    
                       // 结果视图对象的处理
                      applyDefaultViewName(processedRequest, mv);
                      // 拦截器postHandle方法处理
                         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);
                }
    
            }
        }
    
    

    getHandlerAdapter(Object handler)

     @Nullable
        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            // handlerMappings在启动时预先注册
            if (this.handlerMappings != null) {
                Iterator var2 = this.handlerMappings.iterator();
    
                while(var2.hasNext()) {
                    HandlerMapping mapping = (HandlerMapping)var2.next();
                    // 获取处理器执行链
                    HandlerExecutionChain handler = mapping.getHandler(request);
                    if (handler != null) {
                        return handler;
                    }
                }
            }
    
            return null;
        }
    

    processDispatchResult()

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
            boolean errorView = false;
            if (exception != null) {
                if (exception instanceof ModelAndViewDefiningException) {
                    this.logger.debug("ModelAndViewDefiningException encountered", exception);
                    mv = ((ModelAndViewDefiningException)exception).getModelAndView();
                } else {
                    Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                    mv = this.processHandlerException(request, response, handler, exception);
                    errorView = mv != null;
                }
            }
    
            if (mv != null && !mv.wasCleared()) {
                
                 // 渲染
                this.render(mv, request, response);
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("No view rendering, null ModelAndView returned.");
            }
    
            // Concurrent handling started during a forward
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.triggerAfterCompletion(request, response, (Exception)null);java
                }
    
            }
        }
    
    

    render()

    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 != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
        response.setLocale(locale);
        
        // We need to resolve the view name.
          // 解析视图名获取视图对象
        String viewName = mv.getViewName();
        View view;
        if (viewName != null) {
            view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
            if (view == null) {
                throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.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 '" + this.getServletName() + "'");
            }
        }
    
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Rendering view [" + view + "] ");
        }
    
        try {
            if (mv.getStatus() != null) {
                response.setStatus(mv.getStatus().value());
            }
    
              // 委托给视图进行渲染
            view.render(mv.getModelInternal(), request, response);
        } catch (Exception var8) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Error rendering view [" + view + "]", var8);
            }
    
            throw var8;
        }
    }
    

    3.销毁

  • 相关阅读:
    Logistic 与 softmax
    opencv::KMeans图像分割
    opencv::KMeans方法概述
    opencv::opencv_traincascade.exe
    opencv::opencv_createsamples.exe
    opencv::视频人脸检测
    opencv实践::对象提取与测量
    opencv实践::透视变换
    opencv实践::对象计数
    opencv实践::对象的提取
  • 原文地址:https://www.cnblogs.com/aaaazzzz/p/13188422.html
Copyright © 2011-2022 走看看