前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringMVC工作原理流程(二)

SpringMVC工作原理流程(二)

作者头像
秋白
发布2019-02-21 09:53:59
4850
发布2019-02-21 09:53:59
举报
文章被收录于专栏:java小白java小白

SpringMVC具体处理请求

一、处理请求介绍

当有请求过来,首先会先调用HttpServlet的service(ServletRequest req, ServletResponse res)方法,在service方法内部调用service(HttpServletRequest request, HttpServletResponse response)方法(这个service是重载方法,参数类型不同),FrameworkServlet对这个方法重写了。FrameworkServlet方法内部会调用父类的service(HttpServletRequest request, HttpServletResponse response)方法,父类的service(HttpServletRequest request, HttpServletResponse response)方法对不同的请求类型进行了划分,比如doGet,doPost,doXXX,FrameworkServlet对每个请求类型都做了方法重写,在方法内部,都统一调用processRequest(request, response)方法进行处理。processRequest(request, response)内部会对不同请求类型请求处理。

HttpServlet类

代码语言:javascript
复制
    public void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException
    {
	HttpServletRequest	request;
	HttpServletResponse	response;
	
	try {
	    request = (HttpServletRequest) req;
	    response = (HttpServletResponse) res;
	} catch (ClassCastException e) {
	    throw new ServletException("non-HTTP request or response");
	}
	//调用FrameworkServlet的Service方法
	service(request, response);
    }

FrameServlet类

代码语言:javascript
复制
 @Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
		if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
			//统一处理请求
			processRequest(request, response);
		}
		else {
			//调用HttpServlet的service
			super.service(request, response);
		}
	}

HttpServlet类

代码语言:javascript
复制
protected void service(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	String method = req.getMethod();

	if (method.equals(METHOD_GET)) {
	    long lastModified = getLastModified(req);
	    if (lastModified == -1) {
		doGet(req, resp);
	    } else {
		long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
		if (ifModifiedSince < (lastModified / 1000 * 1000)) {
		    maybeSetLastModified(resp, lastModified);
		    doGet(req, resp);
		} else {
		    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
		}
	    }

	} else if (method.equals(METHOD_HEAD)) {
	    long lastModified = getLastModified(req);
	    maybeSetLastModified(resp, lastModified);
	    doHead(req, resp);

	} else if (method.equals(METHOD_POST)) {
	    doPost(req, resp);
	    
	} else if (method.equals(METHOD_PUT)) {
	    doPut(req, resp);	
	    
	} else if (method.equals(METHOD_DELETE)) {
	    doDelete(req, resp);
	    
	} else if (method.equals(METHOD_OPTIONS)) {
	    doOptions(req,resp);
	    
	} else if (method.equals(METHOD_TRACE)) {
	    doTrace(req,resp);
	    
	} else {
	   	String errMsg = lStrings.getString("http.method_not_implemented");
	    Object[] errArgs = new Object[1];
	    errArgs[0] = method;
	    errMsg = MessageFormat.format(errMsg, errArgs);
	    
	    resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
	}
    }

Framework对每个doXXX方法都进行了重写,除了doHead的请求类型。

代码语言:javascript
复制
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

每个doXXX内部都一样代码。

二、处理请求实现

processRequest方法是FrameworkServlet类处理请求的核心方法

代码语言:javascript
复制
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		Throwable failureCause = null;
		//获取与当前线程绑定的localContext对象
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		//构造新的LocaleContext
		LocaleContext localeContext = buildLocaleContext(request);
		//获取与当前线程绑定的RequestAttributes对象
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		//构造新的LocaleContext
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
		//新构建的localeContext和requestAttributes与当前线程绑定,并且设置值
		initContextHolders(request, localeContext, requestAttributes);
		try {
			//抽象方法,具体实现在DispatherServlet
			doService(request, response);
		}
		catch (ServletException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (IOException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (Throwable ex) {
			failureCause = ex;
			throw new NestedServletException("Request processing failed", ex);
		}

		finally {
			//doService执行完之后,恢复原来的previousLocaleContext和previousAttributes
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				//request已经执行完成,不可赋值
				requestAttributes.requestCompleted();
			}

			if (logger.isDebugEnabled()) {
				//省略日志
			}
			//无论请求是否成功,都会发布信息
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

doService方法

代码语言:javascript
复制
@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//判断是否是include请求
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		//设置属性
		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);
		}
		finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// Restore the original attribute snapshot, in case of an include.
				if (attributesSnapshot != null) {
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
		}
	}

doDispather()方法

代码语言:javascript
复制
	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);

				//根据Request查找Handler
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				//根据Handler查找HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// 处理GET,HEAD请求的lastModified
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
				//执行相应Interceptor的preHandle
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// HandlerAdapter使用Handler处理请求
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				//当view为空时,根据request设置默认view
				applyDefaultViewName(processedRequest, mv);
				//执行相应的Interceptor的postHandle
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				//处理返回结果。包括处理异常、渲染页面、发出完成通知触发Interceptor的afterCompletion
				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 {
				//删除上传请求资源
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

解释三个概念

Handler:用@RequestMapping标注的所有方法都可以看做Handler。

HandlerMapping:根据Request查找Handler。

HandlerAdapter:因为SpirngMVC的Handler是任意形式的,所以需要HandlerAdapter执行任意形式的Handler。

doDispatch()方法主要做4件事

  1. 根据Request查找Handler
  2. 根据Handler查找HandlerAdapter
  3. HandlerAdapter使用Hanler处理请求
  4. 调用processDispatchResult返回结果
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年06月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringMVC具体处理请求
    • 一、处理请求介绍
      • 二、处理请求实现
        • doService方法
        • doDispather()方法
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档