SpringMVC 原理

一.Spring运行原理

  1. 用户发起请求到前端控制器DispatcherServlet;
  2. 前端控制器DispatcherServlet 请求处理器映射器HandlerMappering 去查询对应的处理器 (Handler)
  3. 前端控制器DispatcherServlet 调用处理器适配器去执行处理器(Handler),返回视图 (ModelAndView)
  4. 前端控制器DispatcherServle 请求视图解析器(ViewResolver)去进行视图解析,返回View
  5. 前端控制器DispatcherServle 将View进行渲染 返回用户

1.相关组件

前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。

处理器映射器(HandlerMapping):根据URL去查找处理器

处理器(Handler):(需要程序员去写代码处理逻辑的)

处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)

视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面

二.源码分析

DispatcherServlet

1.HttpServletBean

    @Override
	public final void init() throws ServletException {
	    ... ...
		try {
			PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),                             this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new         ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		}
		... ...
		initServletBean();

	}

DispatcherServlet 的 init() 方法在其父类 HttpServletBean 中实现的,它覆盖了 GenericServlet 的 init() 方法,主要作用是加载 web.xml 中 DispatcherServlet 的 <init-param> 配置,并调用子类的初始化。

在 HttpServletBean 的 init() 方法中调用了 initServletBean() 这个方法,它是在 FrameworkServlet 类中实现的,主要作用是建立 WebApplicationContext 容器(有时也称上下文),并加载 SpringMVC 配置文件中定义的 Bean 到改容器中,最后将该容器添加到 ServletContext 中。

2.FrameworkServlet 

protected final void initServletBean() throws ServletException {
		... ...
		long startTime = System.currentTimeMillis();

		try {
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		... ...

	}
protected WebApplicationContext initWebApplicationContext() {
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;

		if (this.webApplicationContext != null) {
			wac = this.webApplicationContext;
			... ...
		}
		if (wac == null) {
			wac = findWebApplicationContext();
		}
		if (wac == null) {
			wac = createWebApplicationContext(rootContext);
		}

		if (!this.refreshEventReceived) {
			onRefresh(wac); // point
		}
		return wac;
	}

WebApplicationContext 继承于 ApplicationContext 接口,从容器中可以获取当前应用程序环境信息,它也是 SpringMVC 的 IOC 容器

建立好 WebApplicationContext(上下文) 后,通过 onRefresh(ApplicationContext context) 方法回调,进入 DispatcherServlet 类中。onRefresh() 方法,提供 SpringMVC 的初始化。

3.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);
		initFlashMapManager(context);
	}

在 initStrategies() 方法中进行了各个组件的初始化。

二.当有请求发送过来

HttpServlet 提供了 doGet()、doPost() 等方法,DispatcherServlet 中这些方法是在其父类 FrameworkServlet 中实现的doGet()、doPost()又都调用了 processRequest() 方法

FrameworkServlet

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ... ...
        // 由 DispatcherServlet 实现
        doService(request, response);
    ... ...
}

DispatcherServlet

@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		... ...
		// Make framework objects available to handlers and view objects.
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, 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 {
			doDispatch(request, response); //ponit
		}
    ... ...
		
	}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		try {
			ModelAndView mv = null;
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);.
			HandlerExecutionChain mappedHandler = getHandler(processedRequest);
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            ... ...
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
			applyDefaultViewName(request, mv);
			mappedHandler.applyPostHandle(processedRequest, response, mv);
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		
		... ...
	}

DispatcherServlet 的 doService() 方法主要是设置一些 request 属性,并调用 doDispatch() 方法进行请求分发处理,doDispatch() 方法的主要过程是通过 HandlerMapping 获取 Handler,再找到用于执行它的 HandlerAdapter,执行 Handler 后得到 ModelAndView ,ModelAndView 是连接“业务逻辑层”与“视图展示层”的桥梁,接下来就要通过 ModelAndView 获得 View,再通过它的 Model 对 View 进行渲染

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值