MVC架构原理与自行实现一个MVC架构

首先当前主流的 web mvc 框架大部分使用的都是前端控制器模式(FrontController)
前端控制器模式(FrontController)
前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。
包含实体
● 前端控制器(Front Controller) - 处理应用程序所有类型请求的单个处理程序
● 调度器(Dispatcher) - 前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序。
● 视图(View) - 视图是为请求而创建的对象。
UML
● FrontController、Dispatcher 分别当作前端控制器和调度器。
● HomeView 和 StudentView 表示各种为前端控制器接收到的请求而创建的视图。
● 从FrontControllerPatternDemo发出一个请求到FrontController,然后通过Dispatcher进行调度,将请求转发到具体的HomeView或者StudentView,然后返回结果
对应图
在这里插入图片描述

Spring MVC
整体结构

在这里插入图片描述

SpringMVC流程
DispatcherServlet
● SpringMVC 使用一个 Servlet(DispatcherServlet) 代理所有的请求。
● 然后根据映射获取处理器后,将请求发送给对应的处理器处理,较好的分离了每一个处理器的职责。
HandlerMapping
● 由定义请求和处理程序对象之间的映射的对象实现的接口。
● 就是在这个对象里面,封装了我们的url和处理对象之间的关系,
● 有多种类型的封装,其中@Controller 只是其中一种,在RequestMappingHandlerMapping中,除此之外,还有很多类型的。
HandlerExecutionChain
● 封装了 Hadler对象 以及拦截器对象 以方便后续进行调用处理
HandlerAdapter
● 处理适配器, 因为在Spring中Handler的实现方式有很多,除了最基本的@Controller 以外,还有很多其他的实现方式例如HandlerFunction,Servlet等等,所以实现方式不同,进行处理的方式就不一样,自然需要不同的适配器来运行对应的Handler。
流程图
在这里插入图片描述

源码简介
核心doDispatch执行流程

在这里插入图片描述

HandlerMapping
● 从上图可以知道,真正处理流程的最主要的就是获取MappingHandler之后,然后获取对应映射的Handler,然后获取对应的拦截器。
● HandlerMapping 在这个 SpringMVC 体系结构中有着举足轻重的地位,充当着 url 和 Controller 之间映射关系配置的角色。
● 主要有三部分组成:HandlerMapping 映射注册、根据 url 获取对应的处理器、拦截器注册。
初始化initHandlerMethods
AbstractHandlerMethodMapping是HandlerMapping的子类,并且实现了InitializingBean
● 在InitializingBean的afterPropertiesSet中对Handler进行了初始化

 public void afterPropertiesSet() {
      initHandlerMethods();
  }
	protected void initHandlerMethods() {
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

initHandlerMethods
在这里插入图片描述

● 判断 beanType 是否是满足要求的 handler 和检测 handlerMethod 是最为关键的两个过程。
isHandler
● isHandler方法判断是否满足要求的 handler
● 在RequestMappingHandlerMapping的实现中为判断带有Controller注解或者RequestMapping注解

protected boolean isHandler(Class<?> beanType) {
	return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class)
            ||
		AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

detectHandlerMethods简介
● 检测 HandlerMethods 是在 detectHandlerMethods 方法中实现的
● 通过 MethodIntrospector#selectMethods 来选择HandlerMethod
detectHandlerMethods源码简介
1. handler如果是String说是是BeanName,从Spring上下文获取Class,否则之间获取Class
2. 防止代理,获取原始Class
3. 重头戏 MethodIntrospector.selectMethods 从Class中获取的Handle方法
a. 其中getMappingForMethod是抽象方法,每种HandlerMapping的Handle的定义方式可以能不同
4. 注册 Handle和mapping 到 mappingRegistry ,以便后续使用
#1
C

lass<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());


if (handlerType != null) {
    #2
	Class<?> userType = ClassUtils.getUserClass(handlerType);
    #3 
	Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
			(MethodIntrospector.MetadataLookup<T>) method -> {
				return getMappingForMethod(method, userType);
			});
    ...
#4    
methods.forEach((method, mapping) -> {
	Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
	registerHandlerMethod(handler, invocableMethod, mapping);
});

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值