springmvc源码之DispatcherServlet

备注360第三天

说到springmvc源码 肯定是要从DispatcherServlet说起,说到Servlet复习一下其中的方法

public interface Servlet {

    /**
     * servlet容器只调用一次init方法,在实例化servlet之后。初始化方法必须成功完成后,servlet才        
       能接收任何请求。
     * @param config 容器的配置和初始化参数
     */
    public void init(ServletConfig config) throws ServletException;

    /**
        返回一个包含初始化和启动参数的对象。 这个返回的对象是传递给init的参数对象
  
     * @see #init
     */
    public ServletConfig getServletConfig();


    /**
    * 这个方法是等init完成后才可以被执行的,处理请求和相应
    **/
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;

    /**
     *返回有关servlet的信息,例如作者、版本和版权所有。
     */
    public String getServletInfo();

    /**
     * 由servlet容器调用,以向servlet指示正在停止使用。此方法只调用一次,servlet的服务方法中的线程已退出或超时时间过后。在servlet容器调用方法,它将不会在此上再次调用服务方法servlet。
     */
    public void destroy();
}

其中在DispatchServlet中,初始化(init)时,就初始化了各个策略

HttpServletBean的init()方法
@Override
	public final void init() throws ServletException {

		...
		// 让子类实现初始化逻辑.
		initServletBean();
	}

FrameworkServlet的初始化逻辑

@Override
	protected final void initServletBean() throws ServletException {
		... 
            // 初始化web应用上下文
			this.webApplicationContext = initWebApplicationContext();
		...
	}


protected WebApplicationContext initWebApplicationContext() {
		...
		if (!this.refreshEventReceived) {
			// 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.
			synchronized (this.onRefreshMonitor) {
                //手动刷新上下文
				onRefresh(wac);
			}
		}

		...

		return wac;
	}

重点来到DispatcherServlet中,开始初始化策略

@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}
//初始化各个策略
protected void initStrategies(ApplicationContext context) {
        // 初始化上传解析器
		initMultipartResolver(context);
        //初始化语言解析器
		initLocaleResolver(context);
        //初始化主题解析器
		initThemeResolver(context);
        //初始化处理映射器
		initHandlerMappings(context);
        //初始化处理适配器
		initHandlerAdapters(context);
        //初始化异常解析器
		initHandlerExceptionResolvers(context);
        //初始化请求到的视图名称翻译器
		initRequestToViewNameTranslator(context);
        //初始化视图解析器
		initViewResolvers(context);
        //初始化flash映射管理器
		initFlashMapManager(context);
	}

这里主要看初始映射器和适配器

spring系列最讲究拓展性,这里我思考HanderMapping应该可以存在自定义的情况,接下来debug去查看initHandlerMappings

private void initHandlerMappings(ApplicationContext context) {
		...
        //看到这里应该存在自定义的点。
        为什么这么说,拓展点目前看来分两种,
        1、通过先定义接口,之后再通过加载对应实现类的方式拓展的
        2、通过类似观察者模式这种去拓展
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			...
	}

//BeanFactoryUtils类
public static <T> Map<String, T> beansOfTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> result = new LinkedHashMap<>(4);
        //加载HandlerMapping接口的所有类
		result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
		...
		return result;
	}

//AbstractApplicationContext
@Override
	public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBeansOfType(type);
	}

后续就是遍历查找对应类型的类了,查找出来放进去,目前默认的有

后续再一一查看上述各个类的功能

接下来 initHandlerAdapters 也是一样的套路

以上是相当于走完 servlet的init方法

接下来是service方法  也就是请求和相应的过程

首先来看DispatcherServlet的doDispatch方法,也就是整体mvc的请求流程

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
                //检查上传请求
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				//获取请求对应的映射器,其中包含处理类的信息、拦截器信息等
				mappedHandler = getHandler(processedRequest);
                //没有找到就直接返回了
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				//通过映射器找到对应适配器,这里为什么还需要适配器去处理呢,为什么不通过   
                映射器直接去处理呢?
                    这里是因为controller有多种实现方式
                    1、通过@Controller注解方式
                    2、通过继承Controller等
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
                //拦截器的前置处理
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 真正的通过反射去调用对应的处理方法,并返回视图解析器,如果返回的是字符串,则返回null
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
                //申请默认的视图名字
				applyDefaultViewName(processedRequest, mv);
                //拦截器的后置处理
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
            //处理结果
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

小结:

首先是通过Servlet的init方法,进行准备阶段(各种解析器)

接下来请求流程:

  1. DispatcherServlet的service方法进入流程
  2. 先找到处理类的处理映射器,返回带有拦截器、处理类信息等的处理执行链
  3. 通过返回的处理执行链这个类去匹配对应适配器
  4. 执行拦截器链前置处理
  5. 通过适配器通过反射去执行对应的处理方法,并返回视图解析器
  6. 执行拦截器的后置处理
  7. 通过视图解析器找到对应视图返回给用户
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值