一次Http请求到达 SpringMvc做了什么

一次Http请求到达 SpringMvc做了什么

题记

众所周知在Java企业级应用开发的大环境中,Spring Framework的地位举足轻重,之所以会是这样就是因为Spring Framework具备以下几点属性:

1. 基于POJO的轻量级和最小侵入性编程
2. 通过依赖注入和面向接口的松耦合
3. 基于切面和惯性进行声明式编程
4. 通过切面和模板减少样板式编码

Spring Framework具备了以上属性,开发跟后期维护会更加便利,依赖关系的明确使得开发效率有了极大的提高,同时也增强了代码的可读性和健壮性,这也就是Spring Framework深受企业级应用青睐的原因。

本文主要讨论基于Spring Frameworkweb项目开发神器Spring Web Mvc,在mvc构建思想的加持下,web项目的开发及使用变得更加便利,对于Spring Framework的功能只是一带而过,后续会有更多更深入的分析。

Mvc思想

以下是从百科翻译的Mvc思想内容

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。 通常模型对象负责在数据库中存取数据。

View(视图)是应用程序中处理数据显示的部分。 通常视图是依据模型数据创建的。

Controller(控制器)是应用程序中处理用户交互的部分。 通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

浅析Spring Web Mvc

其一:Spring面向Bean的开发为对象管理提供便利。

其二:Mvc思想在Spring Web Mvc中的体现,model的体现主要是数据模型,比如说是Pojo对象数据的模型,View的体现主要是视图模板的渲染,Controller的体现主要是业务逻辑的处理。

从设计模式的角度分析

ViewModel的组合是观察者模式体现,前者随后者的变化而改变;View自身可能会存在多个视图的组合,即组合模式的体现;对于不同的handler处理的流程是一样的,这也是策略模式的体现。

Spring Web Mvc工作流程图

在这里插入图片描述

Spring Web Mvc 初始化

本次不做过多的陈述,详情可以参照之前的一篇文章:Spring Mvc 迁移到Spring Boot

博客地址:https://blog.csdn.net/shang_xs/article/details/86654453
微信公众号来源:https://mp.weixin.qq.com/s?__biz=MzUxMzk4MDc1OQ==&mid=100000061&idx=1&sn=8dd762e1b4b03c4caa31680bb7623eb8&scene=19#wechat_redirect

一次http请求的处理

Spring Wbe Mvc中一次请求首先经由DispatcherServlet#doDispatch开始分发交易

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

    //在Spring3.2之后,支持WebAsync异步处理
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
                //转换请求为多个部分并获得相应的处理器
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// 找到当前请求对应的handler
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 找到当前请求对应的handler适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                //执行拦截器preHandle
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				// 反射调用实际执行的handler,返回ModelAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				applyDefaultViewName(processedRequest, mv);
                //执行拦截器postHandle
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				//此处主要是使@ExceptionHandler处理起作用
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
            //执行拦截器processDispatchResult,当程序正常结束时执行
			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()) {
				// 相当于postHandle 和 afterCompletion
				if (mappedHandler != null) {
                    //该实现在HandlerInterceptorAdapter中也有定义
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
                //清除所有请求的处理所对应的资源占用
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

以上是整个请求过程中对应的流程的实现大纲。接下来我们展开细节讨论:

MultipartResolver

初始化

private void initMultipartResolver(ApplicationContext context) {
		try {
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
            ...
        }

实际执行

protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
    ...
        //校验请求信息,返回check结果
        return this.multipartResolver.resolveMultipart(request);
}

HandlerExecutionChain(handlerMapping)

初始化

private void initHandlerMappings(ApplicationContext context) {
 ...
     this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}

实际执行

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 找到当前请求对应的handler
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
	}

HandlerAdapter

初始化

private void initHandlerAdapters(ApplicationContext context) {
    ...
	this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
}

实际执行

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
                    //找到当前请求对应的handler适配器
                    return adapter;
				...
		}

PreHandle

//执行拦截器pre方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

InvokeHandlerMethod

实际执行方法调用

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

主要实现方法

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    		//执行方法调用
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			//返回ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}

执行方法

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
                            Object... providedArgs) throws Exception {
    //执行参数处理和反射调用
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    //处理返回结果
    this.returnValueHandlers.handleReturnValue(
        returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}

调用首先执行参数处理

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            //此处为主要实现,寻找最匹配的参数处理器,并返回处理结果
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		return args;
	}

然后执行反射方法调用

protected Object doInvoke(Object... args) throws Exception {
    //设置Accessible
    ReflectionUtils.makeAccessible(getBridgedMethod());
    //实际调用
    return getBridgedMethod().invoke(getBean(), args);
}

执行返回结果处理

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
	...
	}

获得ModelAndView

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
		// 返回ModelAndView
		return mav;
	}

执行拦截器post处理

mappedHandler.applyPostHandle(processedRequest, response, mv);

执行processDispatchResult包括异常处理和视图渲染

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
	@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
	@Nullable Exception exception) throws Exception {
	//获得ModelAndView	
    mv = ((ModelAndViewDefiningException) exception).getModelAndView();
	//执行异常处理		
	mv = processHandlerException(request, response, handler, exception);
	errorView = (mv != null);
		if (mv != null && !mv.wasCleared()) {
            //渲染视图
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
				logger.trace("No view rendering, null ModelAndView returned.");
	}	
}

视图解析和渲染

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    String viewName = mv.getViewName();
    if (viewName != null) {
        // 解析视图名称
        view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("");
        }
    }
    else {
        //从ModelAndView中获取视图
        view = mv.getView();
    }
    //视图渲染
    view.render(mv.getModelInternal(), request, response);
}

最终实现最佳匹配渲染

public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
    //主要实现方法
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}

以上所有的源码解析,就是在一次http请求到达,Spring Web Mvc进行的相应处理,不足之处请批评指正!

更多精彩

博客:https://blog.csdn.net/shang_xs
微信公众号: java界的小学生

猜你喜欢

转载自blog.csdn.net/shang_xs/article/details/86672003