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返回,完成响应。

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