spring mvc主流程源码阅读(剖析)

第一步,通过web.xml的配置可以知道,用户访问url第一次先走到DispatchServlet,(默认你学过基本的java的Servlet开发)

<servlet>
		<servlet-name>springServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
</servlet>

DispatchServlet类重点阅读

//初始化HandlerMap
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    if (this.detectAllHandlerMappings) {
        Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            //解析xml的 映射关系后,存放到 handlerMapping 后面会用到
            this.handlerMappings = new ArrayList(matchingBeans.values());
            OrderComparator.sort(this.handlerMappings);
        }
    } else {
        try {
            HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        } catch (NoSuchBeanDefinitionException var3) {
            ;
        }
    }

    if (this.handlerMappings == null) {
        this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
        }
    }

}

下图为断点观察效果

ecd44e9e09f539c4f9e591e366f662fa2ee.jpg

d6948b8f8d5da04269115b67aba4de01e9f.jpg

从上图看到,其实这个map就是从spring-mvc.xml文件中读取的不同类型的映射,标准映射、静态资源、拦截器映射等

 

//初始化Adapters
private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    if (this.detectAllHandlerAdapters) {
        Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList(matchingBeans.values());
            OrderComparator.sort(this.handlerAdapters);
        }
    } else {
        try {
            HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);
            this.handlerAdapters = Collections.singletonList(ha);
        } catch (NoSuchBeanDefinitionException var3) {
            ;
        }
    }

    if (this.handlerAdapters == null) {
        this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("No HandlerAdapters found in servlet '" + this.getServletName() + "': using default");
        }
    }

}

 

ac6410ddc94257048194d8ecece25371bb8.jpg

然后,通过断点+源码玩起来了,我这里是通过一个接口测试的,

首先执行 doService方法

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (this.logger.isDebugEnabled()) {
        String requestUri = urlPathHelper.getRequestUri(request);
        String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
        this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + requestUri + "]");
    }

    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        this.logger.debug("Taking snapshot of request attributes before include");
        attributesSnapshot = new HashMap();
        Enumeration attrNames = request.getAttributeNames();

        label113:
        while(true) {
            String attrName;
            do {
                if (!attrNames.hasMoreElements()) {
                    break label113;
                }

                attrName = (String)attrNames.nextElement();
            } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

            attributesSnapshot.put(attrName, request.getAttribute(attrName));
        }
    }

    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());
    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 {
        if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            return;
        }

        if (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;
            Exception dispatchException = null;

            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                mappedHandler = this.getHandler(processedRequest, false);//额这里无语了点了好几层才找到最终获取的Handler
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }

                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());//获取对应的adaptor
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (this.logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        this.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 {
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//执行方法
                } finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                }

                this.applyDefaultViewName(request, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var28) {
                dispatchException = var28;
            }

            this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        } catch (Exception var29) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
        } catch (Error var30) {
            this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            return;
        } else {
            if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }
}

获取handler

f2585cd78590fce6d746ad19c0a85bbe2e5.jpg

handler封装HandlerExecutionChain,从代码来看就是把拦截器相关信息补充进去

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
    chain.addInterceptors(this.getAdaptedInterceptors());
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    Iterator i$ = this.mappedInterceptors.iterator();

    while(i$.hasNext()) {
        MappedInterceptor mappedInterceptor = (MappedInterceptor)i$.next();
        if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
            chain.addInterceptor(mappedInterceptor.getInterceptor());
        }
    }

    return chain;
}

 

从handlerMap中获取Adaptors,

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    Iterator i$ = this.handlerMappings.iterator();

    HandlerExecutionChain handler;
    do {
        if (!i$.hasNext()) {
            return null;
        }

        HandlerMapping hm = (HandlerMapping)i$.next();
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
        }

        handler = hm.getHandler(request);
    } while(handler == null);

    return handler;
}

执行adaptor,最后利用了反射执行代理类的方法

01d97c38e57d1e89d628233370f9ecae2de.jpg

执行后的返回视图逻辑

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
    modelFactory.updateModel(webRequest, mavContainer);
    if (mavContainer.isRequestHandled()) {
        return null;
    } else {
        ModelMap model = mavContainer.getModel();
        ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
        if (!mavContainer.isViewReference()) {
            mav.setView((View)mavContainer.getView());
        }

        if (model instanceof RedirectAttributes) {
            Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes();
            HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
        }

        return mav;
    }
}

总结:url->dispatchServlet->doService->doDispatch->根据url,从handlerMap获取handler,然后根据handler获取adaptor,通过adaptor执行要运行的方法,然后返回页面或者接口数据(返回的逻辑没来得及细看)

在这里即使用到了工厂模式、代理模式、和适配器模式

转载于:https://my.oschina.net/haitaohu/blog/3066541

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值