总结:SpringMVC的处理请求过程?

本文详细介绍了SpringMVC的工作原理及请求处理流程,包括前端控制器DispatcherServlet如何接收和分发请求,以及HandlerMapping、HandlerAdapter、ViewResolver等核心组件的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMvc的处理请求过程?

SpringMvc的说明?
SpringMVC是一种基于JAVA实现了WEB MVC设计模式的请求驱动类型的轻量级WEB框架。目的就是为了简化开发。

请求处理过程:
(1)用户发送请求到前端控制器,前端控制器根据请求URL信息选择对应的页面处理器进行处理。
(2)页面处理器接收到请求信息后,进行功能逻辑处理,首先要将判断并将请求的参数绑定到一个对象上,然后将这个对象委托给业务对象去做业务逻辑处理,(业务实现层)处理完成后会返回一个ModelAndView对象。并且将这个对象发送到前端控制器。
(3)前端控制器根据你的ModelAndView对象(ModelAndView这个对象包含了业务逻辑处理得到的数据模型和对应要渲染展示的逻辑视图名称)。配合视图解析器找到对应的逻辑处理、视图形式、数据模型进行视图渲染。
(4)按照一定规则完成渲染的结果再次发送给前端控制器,前端控制器根据渲染的结果响应到对应的客户端展示界面上。用户能在客户端看到这个响应结果,至此SpringMVC的请求算是处理结束了。
在这里插入图片描述

上述处理过程对应的核心处理接口和实现
(前端控制器其实就是一个DispatcherServlet)
在这里插入图片描述
DispatcherServlet:解释:
DispatcherServlet是一个前端控制器,配置在web.xml中,【作用是:分析拦截匹配的请求,具体的拦截规则要自己定义】把过滤拦截下来的请求分配根据对应的规则找到对应的Controller去处理。
【这里注意一下,它自己本身不干活,不管谁给他发送请求、发送什么请求,他都不做处理,而是按照一定规则拦截过滤,然后找到对应的控制器把请求下发下去,他们去处理,它自己负责全局流程控制】

在web.xml中的大概配置:

<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping></web-app>

了解一下DispatcherServlet的部分源码:
追溯一下DispatcherServlet
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上,追溯一下DispatcherServlet的源码,可以发现它本质就是一个servlet。

总结DispatcherServlet:
DispatcherServlet本质就是一个servlet,这个servlet是实现spring mvc的前端控制,所有的web请求都需要通过它来处理,进行匹配、转发、数据处理。
作为一个servlet,在它的生命周期中,将调用init()方法,完成相关初始化工作,HttpServletBean中重写了init()方法,获取servlet的初始化参数,并进行设置,然后调用子类FrameworkServlet中的initServletBean()方法继续进行初始化,在这个方法中又调用initWebApplicationContext()来初始化web应用上下文。在initWebApplicationContext()方法中通过WebApplicationContextUtils工具类来获取web应用上下文。调用createWebApplicationContext()方法来创建需要与该Servlet相关联的WebApplicationContext,在createWebApplicationContext()方法中通过BeanUtils反射实例化具体的上下文对象,然后调用configureAndRefreshWebApplicationContext()方法设置ServletContext引用,以及其他对象的设置,在createWebApplicationContext()方法中,调用了onRefresh()函数,这个函数在DispatcherServlet中被重写了,它调用了initStrategies()方法,而在这个方法中可以看出来,MVC初始化都是通过这个方法来实现的,这个方法中实现了各种MVC框架实现元素(request映射的HandlerMapping、handler适配处理器的HandlerAdpters,以及视图生成器ViewResolver等。)

【HttpServletBean中重写的init()代码】
HttpServletBean中重写的init()方法
【FrameworkServlet冲的initServletBean()方法】
在这里插入图片描述【FrameworkServlet中的initWebApplicationContext()方法】
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述

总结一下springmvc的核心处理流程?

在这里插入图片描述
【1】用户通过客户端发送请求,请求到前端控制器(DispatcherServlet)。
【2】前端控制器将请求委托给映射处理器(HandlerMapping)。
【3-4】映射处理器根据请求URL,将请求映射成HandlerExecutionChain对象并返回给控制器。(这里并不是简单的返回,而是将处理器和拦截器封装,形成一个处理器执行链HandlerExecutionChain)
【5】控制器根据处理器执行链找到对应的适配处理器(HandlerAdapter)【这里,因为处理器Handler有很多种,前端控制没有办法统一管理,所以出现了适配器,让适配器去处理Handler,而前端控制器只需要管理适配器就行了】
【6-7】适配处理器根据适配结果调用真正的功能处理方法,完成功能处理并返回一个ModelAndView对象(这个对象包含数据模型和逻辑视图名称)。
【8】把得到ModelAndView返回给前端控制器。
【9】前端控制器把ModelAndView中的逻辑视图名传给视图解析器。
【10】视图解析器(ViewResolver)根据逻辑视图名解析成对应的view视图对象并返回给控制器。
【11】前端控制器结合返回的view视图对象和ModelAndView中的数据模型渲染成对应的展示界面结果。并将渲染后的结果返回给控制器。
【13】前端控制器根据返回的渲染结果响应请求到客户端,用户可以在客户端看到渲染效果,至此整个请求过程处理完成。

大概走一下一些关键方法的调用,上面走过了整个mvc初始化的大概方法,这里不重复。
(1)上述,SpringMVC完成初始化后,对Http请求是在DispatcherServlet中封装的“ protected void doService(HttpServletRequest request, HttpServletResponse response) ”方法:[源码]主要目的是保存一些请求参数和框架中的一些全局变量设置到请求中。这些都完成后调用doDispatch(request,response)

/**
	 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
	 * for the actual dispatching.
	 */
	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isDebugEnabled()) {
			String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
			logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
					" processing " + request.getMethod() + " request for [" + getRequestUri(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<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));
				}
			}
		}

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

doDispatch(request, response);分发请求
这个方法是DispatcherServlet完成请求分发的核心方法,源码如下:【通过HandlerMapping获取请求所对应的handler,之后选择合适的 HandlerAdapter(适配器)】,通过适配器调用对应的handler处理相应的请求,并返回ModelandView对象,通过视图解析器ViewResolver对视图解析得到view,并通过view对象渲染最后呈现结果。(里面的方法源码,有兴趣的去看一下)

	/**
	 * Process the actual dispatching to the handler.
	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 * to find the first that supports the handler class.
	 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
	 * themselves to decide which methods are acceptable.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @throws Exception in case of any kind of processing failure
	 */
	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);

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				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 (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

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

				// Actually invoke the 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);
				}
			}
		}
	}

HandlerMapping的源码,主要是一个关键方法getHandler();
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值