springMVC源码简读——3.1 请求处理

处理请求入口方法

mvc整个请求的过程

graph TD
A(用户) -->|1发送请求| B(DispatcherServlet)

B --> |2映射处理器| C(HandlerMapping)


C --> |3返回拦截器和处理器|B

B --> |4处理器适配| D(HandlerAdapter)

D --> |5调用处理器方法| E(处理器)

E --> |6处理后返回视图模型对象 |D

D --> |7继续返回给HandlerAdapter| B

B --> |8视图模型对象通过解析器进行解析| F(视图解析器)

F --> |9视图渲染| G(视图)

G --> |10返回给用户| A

吐槽csdn啥时候可以支持md的流程图啊
在这里插入图片描述

请求涉及的类

FrameworkServlet

是请求中实际负责业务的类,主要涉及的方法为

  • #doGet(HttpServletRequest request, HttpServletResponse response)
  • #doPost(HttpServletRequest request, HttpServletResponse response)
  • #doPut(HttpServletRequest request, HttpServletResponse response)
  • #doDelete(HttpServletRequest request, HttpServletResponse response)
  • #doOptions(HttpServletRequest request, HttpServletResponse response)
  • #doTrace(HttpServletRequest request, HttpServletResponse response)
  • #service(HttpServletRequest request, HttpServletResponse response)

HttpMethod 请求的特殊处理

service

因为 HttpServlet 默认没提供 #doPatch方法,所以只能通过父类的 #service(…) 方法,从而实现

// FrameworkServlet.java

protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 获得请求方法
		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
		// 处理 PATCH 请求 若请求方法是 HttpMethod.PATCH则使用processRequest进行处理,因为spring默认没有
		// 提供doPatch的处理方法
		if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
			processRequest(request, response);
		}
		// 调用父类,处理其它请求
		else {
			super.service(request, response);
		}
	}
	

当请求为PATCH的时候,会调用processRequest方法,而其他类型的则会调用父类的service方法

父类的service,也就是javax.servlet.http.HttpServlet.java的方法

这一部分属于java的代码范围了。

    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) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    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);
        }
    }

doGet & doPost & doPut & doDelete

这四个方法和上面patch最终都是调用processRequest方法

/ FrameworkServlet.java
@Override
	protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}
	
	// 其他的类似

doOptions 和 doTrace

两者逻辑差不多都是进行处理后调用java的HttpServlet的方法

/ FrameworkServlet.java

protected void doOptions(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 如果 dispatchOptionsRequest 为 true ,则处理该请求
		if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
			// 处理请求
			processRequest(request, response);
			// 如果响应 Header 包含 "Allow" ,则不需要交给父方法处理
			if (response.containsHeader("Allow")) {
				// Proper OPTIONS response coming from a handler - we're done.
				return;
			}
		}

		// Use response wrapper in order to always add PATCH to the allowed methods
		// 调用父方法,并在响应 Header 的 "Allow" 增加 PATCH 的值
		super.doOptions(request, new HttpServletResponseWrapper(response) {
			@Override
			public void setHeader(String name, String value) {
				if ("Allow".equals(name)) {
					value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
				}
				super.setHeader(name, value);
			}
		});
	}
	
		protected void doTrace(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 如果 dispatchTraceRequest 为 true ,则处理该请求
		if (this.dispatchTraceRequest) {
			// 处理请求
			processRequest(request, response);
			// 如果响应的内容类型为 "message/http" ,则不需要交给父方法处理
			if ("message/http".equals(response.getContentType())) {
				// Proper TRACE response coming from a handler - we're done.
				return;
			}
		}
		// 调用父方法
		super.doTrace(request, response);
	}

processRequest

可以看到上面几乎所有的方法都会调用到这个方法,这个方法也是对请求处理的核心逻辑

// FrameworkServlet.java
try {
			// 执行逻辑
			// 该抽象方法由 DispatcherServlet 实现,
			// 所以这就是 DispatcherServlet 处理请求的真正入口
			doService(request, response);
		}
		catch (ServletException | IOException ex) {
			failureCause = ex;
			throw ex;
		}
		

方法前面几行获得了很多参数,但是最终的业务逻辑在doService这里。而这个方法的实现不在FrameworkServlet。而在DispatcherServlet里面

DispatcherServlet

doService

处理请求的入口方法

// DispatcherServlet.java
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 打印请求日志,并且日志级别为 DEBUG
		logRequest(request);

		// Keep a snapshot of the request attributes in case of an include,
		// to be able to restore the original attributes after the include.
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<>();
			// 获得属性集合,并且将属性设置到属性快照中
			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));
				}
			}
		}

		// Make framework objects available to handlers and view objects.
		// 设置 Spring 框架中的常用对象到 request 属性中
		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());

		// flashMapManager,进行缓存,并设置
		if (this.flashMapManager != null) {
			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);
				}
			}
		}
	}
	

请求的逻辑被放到doDispatch中了

doDispatch

执行请求的分发的核心逻辑,包含了获得处理器Handler,获得处理适配器HandlerAdapter,前置处理,拦截处理,默认视图了,后置处理

// DispatcherServlet.java
	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 {
				// 检查是否是请求multipart,是的话使用multipartResolver解析
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				// 获得请求对应的 HandlerExecutionChain 对象,请求处理器的映射
				mappedHandler = getHandler(processedRequest);
				// 假如没有拿到处理器
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				// 获得当前 handler 对应的 HandlerAdapter 对象,根据处理器获得对应的适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				// last-modified
				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;
				}

				// Actually invoke the handler.
				// 真正的调用 handler 方法,并返回视图
				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);
				}
			}
		}
	}

getHandler

获得处理器

// DispatcherServlet.java

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 处理映射的集合
		if (this.handlerMappings != null) {
			// 遍历 HandlerMapping 数组
			for (HandlerMapping mapping : this.handlerMappings) {
				// 获得请求对应的 HandlerExecutionChain 对象
				HandlerExecutionChain handler = mapping.getHandler(request);
				// 获得到,则返回
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}
	

这一部分代码可以查看HandlerMapping模块的内容

getHandlerAdapter

通过处理器获得处理器对应的适配器

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			// 遍历 HandlerAdapter 数组
			for (HandlerAdapter adapter : this.handlerAdapters) {
				// 判断是否支持当前处理器
				if (adapter.supports(handler)) {
					// 如果支持,则返回
					return adapter;
				}
			}
		}
		// 没找到对应的 HandlerAdapter 对象,抛出 ServletException 异常
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

这一部分代码可以查看HandlerAdapter模块的内容

applyPreHandle

拦截操作和前置处理

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 获得拦截器数组
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			// 遍历拦截器数组
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				//  前置处理
				if (!interceptor.preHandle(request, response, this.handler)) {
					// 触发已完成处理
					triggerAfterCompletion(request, response, null);
					// 返回 false ,前置处理失败
					return false;
				}
				// 标记 interceptorIndex 位置
				this.interceptorIndex = i;
			}
		}
		// 返回 true ,前置处理成功
		return true;
	}

这一部分代码可以查看HandlerMapping模块的拦截器内容

applyPostHandle

后置处理

	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {
		// 获得拦截器数组
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			// 遍历拦截器数组
			// 倒序
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				// 后置处理
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}

这一部分代码可以查看HandlerMapping模块的拦截器内容

processDispatchResult

处理正常和异常的请求调用结果

// DispatcherServlet.java
	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		// 标记,是否是生成的 ModelAndView 对象
		boolean errorView = false;

		// 如果是错误结果
		if (exception != null) {
			// 情况一,从 ModelAndViewDefiningException 中获得 ModelAndView 对象
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			// 情况二,处理异常,生成 ModelAndView 对象
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				// 标记 errorView
				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) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

假如是异常则使用异常的错误视图处理,假如是正常就根据viewAndmodel来渲染视图对象view

render

进行视图的渲染

// DispatcherServlet.java

	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		// 从 request 中获得 Locale 对象,并设置到 response 中
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName();
		// 使用viewName获得视图对象
		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.
			// 或者直接从mv中获得视图对象
			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;
		}
	}

根据ModelAndView进行渲染操作,在视图渲染组件里面已经讲过了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值