SpringMVC详细详细过程

SpringMVC过程

在这里插入图片描述
在这里插入图片描述
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 {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
                
                // 检查是否为文件上传请求
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

                // 2、3、4
				// Determine handler for the current request.
                // 根据当前请求找到哪个类能来处理,返回的对象为HandlerExecutionChain
                // HandlerMapping存储了所有请求和处理器之间的关系,HandlerExecutionChain表示某一个请求和处理器之间的关系,列表·循环·非null返回Handler
                // mappedHandler即为图中的HandlerExecution
				mappedHandler = getHandler(processedRequest);
                // 如果没有找到Handler能处理这个请求,
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

                // 5、8
				// Determine handler adapter for the current request.
                // 根据mappedHandler也就是图中的HandlerExcution也就是HandlerExecutionChain类的对象,找到对应的HandlerAdapter(反射工具AnnotationMethodHandlerAdapter)
                //查找方式和上面查找HandlerExcutionChain一样,在列表中用for循环查找
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
                // 获取请求方式
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

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

                //6、7
				// Actually invoke the handler.真正的执行处理器的方法
                // 处理器的方法被调用,(HandlerAdapter调用Controller,图中6、7步,ha即HandlerAdapter)
                // 即Controller方法的语句执行,比如你在Controller类中有一个log.info("aaa")或"aaa".sout,这时候运行完这行代码,命令行里就有了aaa的输出了
                // 返回ModelAndView,保存Controller方法返回值作为视图名
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				// 如Controller没有返回值,则设置默认的视图名
				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);
			}
            
            // 9、10、11、12
            // 转发到目标页面
            // processedRequest(包装后的Request(检查是否为文件传输的Request))
            // 根据方法最终执行完成后封装的ModelAndView,转发到对应页面,同时ModelAndView中的Model即数据也可以从请求域中获取。该方法见下文
			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);
				}
			}
		}
	}
// 图1中 3 查找Handler 获得图中的HandlerExecution即HandlerExecutionChainll类的对象
@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

HandlerMapping接口有两个实现类,基于配置文件的和基于注解的
在这里插入图片描述

// 图1中 5
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;

		if (exception != null) {
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			// Exception (if any) is already handled..
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}
/**
	 * Render the given ModelAndView.
	 * <p>This is the last stage in handling a request. It may involve resolving the view by name.
	 * @param mv the ModelAndView to render
	 * @param request current HTTP servlet request
	 * @param response current HTTP servlet response
	 * @throws ServletException if view is missing or cannot be resolved
	 * @throws Exception if there's a problem rendering the view
	 */
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName();
		if (viewName != null) {
			// We need to resolve the view name.
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			view = mv.getView();
			if (view == null) {
				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
						"View object in servlet with name '" + getServletName() + "'");
			}
		}

		// Delegate to the View object for rendering.
		if (logger.isTraceEnabled()) {
			logger.trace("Rendering view [" + view + "] ");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}

总结:

所有请求都会被DispatcherServlet接受并拦截

继承了HttpServlet类,还是相当于实现了doGet和doPost方法。命令提交到服务器,DispatcherServlet执行doService方法,doService方法调用doDispatch方法。

  1. doDispatch方法首先检查request参数是不是文件上传请求,并对参数HttpServletRequest的对象包装。

  2. 然后调用getHandler方法,这个方法的返回值是HandlerExecutionChain类的对象,getHandler方法就是在handlerMapping列表中for循环查找HandlerExecutionChain,handlerMapping就是包含了所有HandlerExecutionChain对象的一个列表
    在这里插入图片描述

  3. 找到关于这个请求的HandlerExecutionChain对象,在将这个对象的getHander方法返回的handler作为参数调用getHandlerAdapter方法在HandlerAdapters列表中查找handlerAdapter

  4. 得到的HandlerAdapter对象会调用hadle方法,在这个方法执行时,就是controller方法执行的时候。同时这个方法返回的是ModelAndView对象。

  5. 然后这个doDispatch方法会把ModelAndView作为参数调用processDispatchResult方法,在这个方法中又会调用render方法,再通过reder方法里的resolveViewName方法返回真正的视图名,在转发到视图,并可以在请求域中取出ModelAndView中的模型数据。


英语学习:

mapping 测绘

execution 执行

adapter 适配器

dispatcher 分发器

resolver 分解器

chain 锁链

interceptors 拦截器

render 提供

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值