雷丰阳SpringMVC01——源码

P156 DispatcherServlet 源码分析

找doGet 和doPost方法(继承Httpservlet后重要的两个方法): 发现里面调用了processRequest()方法
在这里插入图片描述
发现在 processRequest() 重点是调用了
doService()
方法
在这里插入图片描述
doService() 是本类也就是FrameworkServlet中的抽象方法 所以需要找实现了doService()方法(在DispatcherServlet中)
在这里插入图片描述
在DispatcherServlet 中找到了doService的实现方法
在这里插入图片描述
最重要的地方:
在这里插入图片描述
try中的内容比较重要!
重点: doDispathch方法 (该方法在本类DispatcherServlet中定义)

总结:

在这里插入图片描述
重点:研究doDispatch()该方法

P157 基本的请求流程

doDispatch() 两个关键的位置:

1.目标方法执行:

在这里插入图片描述

2.页面跳转

在这里插入图片描述

3.大体流程:

在这里插入图片描述
重点看第二步

getHandler() 方法(第二步)

在这里插入图片描述
返回值中的handler封装了处理对应请求的处理器类(Controller)

getHandlerAdapter()(第四步)

拿到处理器类对应的适配器来执行目标方法(看作是一个反射工具)
在这里插入图片描述

返回值为处理注解方法的适配器 ha

ha.handle() (第五步)

适配器执行目标方法 返回值为modelAndView (数据和视图)
在这里插入图片描述

processDispatchResult() (第六步)

在这里插入图片描述

P158 HandlerMapping

doDispatch()总结:
在这里插入图片描述

细节1: getHandler()

在这里插入图片描述
getHandler(processRequest) processRequest 保存了当前请求的地址/hello
在这里插入图片描述

在这里插入图片描述
重点:对getHandler()研究 增强for循环:
在这里插入图片描述
handlerMappings(处理器映射)保存了:每一个处理器能处理哪些请求的 映射信息(每个处理器都加了@Controller的注解,在Spring容器启动时,就创建了对应的对象,扫描注解的过程中将对应的方法和类保存在handlerMap
在handlerMappings中寻找对应的处理器。
在这里插入图片描述
重点:对getHandlerAdaptor()研究
在这里插入图片描述
AnnotationMethodHandlerAdaptor:能解析注解方式的适配器
增强for循环,判断是否支持(是否实现了HttpRequestHandler接口)
在这里插入图片描述
重载的supports方法在这里插入图片描述
在这里插入图片描述

P161 九大组件

总结:
在这里插入图片描述
==探究一下for each() 中 HandlerMappings 和 HandlerAdapters 什么时候有值 ==
在这里插入图片描述
HandlerMappings 和 HandlerAdapters 作为DispatcherServlet的属性

九大组件(DispatcherServlet的属性)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
九大组件全部都是接口,接口就是规范,提供了非常强大的扩展性

DispatcherServlet 中的 onRefresh 方法
在这里插入图片描述
在这里插入图片描述
在服务器一启动的时候就进行初始化
initHandlerMappings() 该初始化方法:
在这里插入图片描述
探查所有handlerMapping在这里插入图片描述
可以手动地修改(web.xml中):
在这里插入图片描述

P163 执行目标方法

拿到适配器进行执行目标方法(反射)的时候,参数的传入是多种多样的,这是一个需要研究的问题!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最终的执行目标方法的地方:传入目标处理器方法、处理器类、包装后的原生request、response、隐含模型(BindingAwareModelMap )
在这里插入图片描述
找到@ModelAttribute注解标注的方法
在这里插入图片描述

resolveHandlerAArguments()解析ModelAttribute方法的参数;
变成可访问的模式,然后进行反射执行
在这里插入图片描述
resolveHandlerArguments() 方法(获取参数)
在这里插入图片描述
针对ModelAttribute方法
在这里插入图片描述
在这里插入图片描述
找注解的过程中,如果某个参数的注解大于一个则抛出异常,因此某个参数中的注解只能有一个。我们这里参数中没有注解,只有Map
在这里插入图片描述
参数注解大于1个,抛出异常
在这里插入图片描述
没有找到注解的情况下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
返回类型的小写作为attrName
在这里插入图片描述
隐含模型中的内容,就是ModelAtrribute标注的方法中添加进去的
在这里插入图片描述
将返回值放到隐含模型中
在这里插入图片描述
执行完ModelAttribute方法后,接下来就执行目标方法。

可以看到:ModelAttribute标注的方法先于目标方法执行,并将自己的返回值放到隐含模型中。
在这里插入图片描述
执行目标方法之前,先要获取目标方法的参数。
在这里插入图片描述
接下来关注:解析目标方法的参数参数 “resolveHandlerArguments()方法”
目标方法的参数:
在这里插入图片描述

	private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
			NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
 		// 获取ModelAttribute方法的参数类型
		Class[] paramTypes = handlerMethod.getParameterTypes();
		// 初始化一个长度大小为参数数组长的返回值
		Object[] args = new Object[paramTypes.length];
 
		for (int i = 0; i < args.length; i++) {
			MethodParameter methodParam = new MethodParameter(handlerMethod, i);
			methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
			GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
			String paramName = null;
			String headerName = null;
			boolean requestBodyFound = false;
			String cookieName = null;
			String pathVarName = null;
			String attrName = null;
			boolean required = false;
			String defaultValue = null;
			boolean validate = false;
			Object[] validationHints = null;
			int annotationsFound = 0;
			// 获得参数上的注解
			Annotation[] paramAnns = methodParam.getParameterAnnotations();
 			// 【判断是什么类型的注解】
			for (Annotation paramAnn : paramAnns) {
				// 判断是否RequestParam注解
				if (RequestParam.class.isInstance(paramAnn)) {
					// 类型转换
					RequestParam requestParam = (RequestParam) paramAnn;
					// 注解的value赋值给 paramName
					paramName = requestParam.value();
					required = requestParam.required();
					defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
					annotationsFound++;
				}
				else if (RequestHeader.class.isInstance(paramAnn)) {
					RequestHeader requestHeader = (RequestHeader) paramAnn;
					headerName = requestHeader.value();
					required = requestHeader.required();
					defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
					annotationsFound++;
				}
				else if (RequestBody.class.isInstance(paramAnn)) {
					requestBodyFound = true;
					annotationsFound++;
				}
				else if (CookieValue.class.isInstance(paramAnn)) {
					CookieValue cookieValue = (CookieValue) paramAnn;
					cookieName = cookieValue.value();
					required = cookieValue.required();
					defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
					annotationsFound++;
				}
				else if (PathVariable.class.isInstance(paramAnn)) {
					PathVariable pathVar = (PathVariable) paramAnn;
					pathVarName = pathVar.value();
					annotationsFound++;
				}
				else if (ModelAttribute.class.isInstance(paramAnn)) {
					ModelAttribute attr = (ModelAttribute) paramAnn;
					attrName = attr.value();
					annotationsFound++;
				}
				else if (Value.class.isInstance(paramAnn)) {
					defaultValue = ((Value) paramAnn).value();
				}
				else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
					validate = true;
					Object value = AnnotationUtils.getValue(paramAnn);
					validationHints = (value instanceof Object[] ? (Object[]) value : new Object[] {value});
				}
			}
 			// 【某个参数的注解个数大于1,抛出异常】
			if (annotationsFound > 1) {
				throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
						"do not specify more than one such annotation on the same parameter: " + handlerMethod);
			}
 			// 【没有注解的参数】
			if (annotationsFound == 0) {
				// 解析普通参数 【原生API】
				Object argValue = resolveCommonArgument(methodParam, webRequest);
				if (argValue != WebArgumentResolver.UNRESOLVED) {
					args[i] = argValue;
				}
				else if (defaultValue != null) {
					args[i] = resolveDefaultValue(defaultValue);
				}
				else {
					// 获得参数类型
					Class<?> paramType = methodParam.getParameterType();
					// 判断是Mode类型或者Map类型
					if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
						if (!paramType.isAssignableFrom(implicitModel.getClass())) {
							throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +
									"Model or Map but is not assignable from the actual model. You may need to switch " +
									"newer MVC infrastructure classes to use this argument.");
						}
						// 传入隐含模型【之前的ModelAtrribute使用后传入的隐含模型】
						args[i] = implicitModel;
					}
					else if (SessionStatus.class.isAssignableFrom(paramType)) {
						args[i] = this.sessionStatus;
					}
					else if (HttpEntity.class.isAssignableFrom(paramType)) {
						args[i] = resolveHttpEntityRequest(methodParam, webRequest);
					}
					else if (Errors.class.isAssignableFrom(paramType)) {
						throw new IllegalStateException("Errors/BindingResult argument declared " +
								"without preceding model attribute. Check your handler method signature!");
					}
					// 【是否是简单类型】基本类型:Integer、String
					else if (BeanUtils.isSimpleProperty(paramType)) {
						paramName = "";
					}
					else {
						attrName = "";
					}
				}
			}
			// 【标了注解,确定注解的值的环节】
 			// paramName中保存的是注解中的value的值 
			if (paramName != null) {
				args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
			}
			else if (headerName != null) {
				args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
			}
			else if (requestBodyFound) {
				args[i] = resolveRequestBody(methodParam, webRequest, handler);
			}
			else if (cookieName != null) {
				args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
			}
			else if (pathVarName != null) {
				args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
			}
			// 确定自定义类型参数的值,还要将请求中的每一个参数赋值给这个对象
			else if (attrName != null) {
				WebDataBinder binder =
						resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
				boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
				if (binder.getTarget() != null) {
					doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
				}
				args[i] = binder.getTarget();
				if (assignBindingResult) {
					args[i + 1] = binder.getBindingResult();
					i++;
				}
				implicitModel.putAll(binder.getBindingResult().getModel());
			}
		}
 		// 返回  ModelAttribute方法中确定的参数
		return args;
	}

P166 确定POJO中的值

在这里插入图片描述

在这里插入图片描述
对于自定义类型的值:
在这里插入图片描述
三步判断确定pojo中的值
在这里插入图片描述
第三步中,如果都没有的话就利用反射创建一个POJO对象,那么其中的部分参数是null。

P167总结

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值