SpringMVC原理(請求流程分析)

SpringMVC最主要的類爲DispatcherServlet,包名爲org.springframework.web.servlet。

該類繼承於FrameworkServlet,FrameworkServlet的類圖如下:

即本質上FrameworkServlet也是一個Servlet,特別的是這個Servlet對應的URI爲*,所有的context path下的請求都會在這個Servlet中處理。

當第一次請求時會執行HttpServletBean類的init方法,其中會讀取相關配置文件並執行FrameworkServlet類中的initServletBean方法:

PropertyValues pvs = new 
HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
        if (!pvs.isEmpty()) {
            try {
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
                bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
                this.initBeanWrapper(bw);
                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;
            }
        }

        this.initServletBean();

initServletBean方法會調用initWebApplicationContext方法初始化Web容器,其中會調用DispatcherServlet類的onRefresh方法,onRefresh調用initStrategies開始初始化策略:

protected void initStrategies(ApplicationContext context) {
        this.initMultipartResolver(context);
        this.initLocaleResolver(context);
        this.initThemeResolver(context);
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
        this.initHandlerExceptionResolvers(context);
        this.initRequestToViewNameTranslator(context);
        this.initViewResolvers(context);
        this.initFlashMapManager(context);
    }

其中會初始化模板解析,url映射關係,異常解析等內容。

所有類型的請求都會通過FrameworkServlet類的processRequest方法進行處理:

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

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

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

processRequest方法則調用DispatcherServlet的doService方法,該方法會進行請求參數處理並調用doDispatch方法開始真正的處理。

在doDispatch方法中,mappedHandler = this.getHandler(processedRequest); 來獲取url和Controller中方法的對應關係,getHandler方法會遍歷初始化時的handlerMappings,並與每個mapping的mappingRegistry中註冊的url進行匹配,下圖爲我的測試代碼匹配過程:

匹配結束後會返回該url匹配的處理方法的信息,例如:

之後調用所有的攔截器的preHandle方法,進行公共處理,處理後調用真正的Controller中代碼,執行結束後調用所有攔截的postHandle方法進行處理:
 

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);

其中handle方法會對返回值做對應的處理,比如將對象轉換爲json字符串,該返回將被轉換爲outputStream並置於response返回,完成響應。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章