首页 > 其他分享 >简述SprintMVC过程

简述SprintMVC过程

时间:2023-09-05 21:49:18浏览次数:35  
标签:-- request 简述 handler 处理器 ModelAndView DispatcherServlet 过程 SprintMVC

SprintMVC

SpringMVC是一个对servlet进行大量封装的Spring框架的组件,,基于MCV架构模式,用于表现层的开发。

SpringMVC中包含两个容器,Spring作为父容器,SpringMVC作为子容器。

简略过程

通过映射器找到url对应的控制器,但控制器需要实现处理器的接口,且有多种方式实现,因此需要适配器确定是哪个处理器接口,确定好处理器接口后,可以直接调用控制器重写的方法,完成控制器的逻辑并返回ModelAndView给DispatcherServlet,DispatcherServlet通过视图解析器将逻辑视图名匹配到视图,然后通过浏览器渲染展示。

= Spring容器和SpringMVC容器启动

= 遍历处理器映射器,获取请求对应的处理器执行链(封装的handler和interceptor)

= 遍历处理器适配器,获取支持处理器的处理器适配器

= 调用适配器的handle方法,执行控制器实现处理器接口的重写方法,完成控制器的逻辑,返回ModelAndView

= 根据ModelAndView获取到Model和View对象,合并Model的数据和request属性,然后对view进行渲染,响应到浏览器

public class DispatcherServlet extends FrameworkServlet {
    private List<HandlerMapping> handlerMappings;
    
}

1、MVC容器启动

// 创建、加载Spring配置并刷新Spring容器(Root WebApplicationContext)
ContextLoader#initWebApplicationContext()
// 初始化Servlet相关的bean,创建并刷新SpringMVC容器
FrameworkServlet#initServletBean()

.......

2、初始化DispatcherServlet策略接口

【通过发布事件及事件监听处理器来】初始化MVC九大组件(DispatcherServlet策略接口) ,DispatcherServlet.properties文件中默认配置了DispatcherServlet策略接口的实现类。

// 初始化HandlerMapping、HandlerAdapter和ViewResolver
protected void initStrategies(ApplicationContext context){
	// 开启detectAll,获取HandlerMapping类型的bean,赋值给handlerMappings列表
    // 关闭detectAll,获取beanName为handlerMapping且类型为HandlerMapping的bean, 赋值给handlerMappings列表
    // handlerMappings==null,获取默认策略的实现类, 赋值给handlerMappings列表
	initHandlerMappings(context);
    // 开启detectAll,获取HandlerAdapter类型的bean,赋值给handlerAdapters列表
    // 关闭detectAll,获取beanName为handlerAdapter且类型为HandlerAdapter的bean, 赋值给handlerAdapters列表
    // handlerAdapters==null,获取默认策略的实现类, 赋值给handlerAdapters列表
    initHandlerAdapters(context);
	// 同上面类似
    initViewResolvers(context);
}

3、请求处理流程

SpringMVC遵循Servlet的生命周期,Servlet生命周期主要有三个重要的方法init()、service()、destory()。

FrameworkServlet#service()		# 接收请求
FrameworkServlet#processRequest()	# 处理LocaleContext和ServletRequestAttributes
FrameworkServlet#doService()	# 
DispatcherServlet#doService()	# 设置HttpServletRequest属性
DispatcherServlet#doDispatch()	# 请求分发【处理实际的请求,分发给handler】

Process the actual dispatching to the handler.

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 从HandlerMapping中获取当前请求对应的HandlerExecutionChain对象 (handler and any interceptors)
	HandlerExecutionChain mappedHandler = getHandler(processedRequest);
    
    // 从HandlerExecutionChain拿到handler对象,再获取handler对应的HandlerAdapter对象
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // Apply preHandle methods of registered interceptors.
    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
        return;
    }
    
    // Actually invoke the handler,返回ModelAndView
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    // view==null,根据request设置默认的view名
    applyDefaultViewName(processedRequest, mv);
    
    // Apply postHandle methods of registered interceptors.
    mappedHandler.applyPostHandle(processedRequest, response, mv);
    
    //处理分发结果
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        
}

getHandler方法中返回请求的HandlerExecutionChain对象

public interface HandlerMapping {
    // Return a handler and any interceptors for this request. 
    // The choice may be made on request URL, session state, 
    // or any factor the implementing class chooses.
    @Nullable
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
    
}
控制器
  • ParameterizableViewController:请求路径url直接到视图
  • AbstractCommandController:

SpringMVC中重写处理器(handle)的三种方式:

  1. 实现HttpRequestHandler接口,重写handleRequest方法
public class TestController implements HttpRequestHandler {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}
  1. 实现Controller接口,重写handleRequest方法
public class TestController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}
  1. @Controller注解
@Controller
public class TestController {
}
映射器

HandlerMapping的三个实现类

DispatcherServlet#doDispatch()
-->DispatcherServlet#getHandler() // 遍历handlerMappings,返回request的HandlerExecutionChain对象(handler and any interceptors)
 -->AbstractHandlerMapping#getHandler() // 获取请求的handler,返回获得的HandlerExecutionChain对象,处理跨域问题
  -->AbstractHandlerMethodMapping#getHandlerInternal() // 查找请求的最优匹配handler method,返回HandlerMethod对象
  -->AbstractHandlerMethodMapping#lookupHandlerMethod() // 返回请求对应的HandlerMethod对象(Controller的beanName、Class对象、method...)
   -->HandlerMethod#createWithResolvedBean() //  获取Controller的beanName,返回 封装handler(Controller)的HandlerMethod对象
  -->AbstractHandlerMapping#getHandlerExecutionChain() // 创建处理器执行链对象,封装handler处理器和添加匹配请求的interceptor拦截器 
    
RequestMappingHandlerMapping#afterPropertiesSet() // RequestMappingInfo.BuilderConfiguration 属性赋值
 -->AbstractHandlerMethodMapping#initHandlerMethods() // Scan beans in the ApplicationContext
 -->AbstractHandlerMethodMapping#processCandidateBean()	// 处理被Controller、RequestMapping注解修饰bean
 -->AbstractHandlerMethodMapping#detectHandlerMethods() // 获取访问路径与控制器方法的映射关系
 -->AbstractHandlerMethodMapping#registerHandlerMethod() // Register a handler method and its unique mapping
适配器

适配器根据supports()判断控制器实现了哪个处理器接口,最后调用控制器重写实现处理器接口的方法,完成控制器的逻辑,返回ModelAndView

DispatcherServlet#doDispatch()
-->DispatcherServlet#getHandlerAdapter() // 遍历handlerAdapters,返回supports(handler)的HandlerAdapter
// 调用HandlerAdapter的handle()方法,完成控制器的逻辑
-->RequestMappingHandlerAdapter#handleInternal()
-->RequestMappingHandlerAdapter#invokeHandlerMethod() // Invoke the RequestMapping handler method preparing a ModelAndView...
-->RequestMappingHandlerAdapter#createInvocableHandlerMethod() // 参数绑定、处理请求以及返回值处理

......
视图解析器

通过ModelAndView对象解析出View对象并且获取Model对象,将Model对象的数据和request的属性合并为mergedModel, 然后设置mergedModel到request属性中;确定request dispatcher的路径,获取请求分发器(RequestDispatcher)进行转发

DispatcherServlet#doDispatch()
-->DispatcherServlet#processDispatchResult() // 处理异常的ModelAndView对象,渲染页面,触发Interceptor的afterCompletion
-->DispatcherServlet#render() // 获取View对象,设置响应状态码,页面渲染,
-->DispatcherServlet#resolveViewName() // 遍历viewResolvers,根据视图名称,解析出View对象

......

标签:--,request,简述,handler,处理器,ModelAndView,DispatcherServlet,过程,SprintMVC
From: https://www.cnblogs.com/jishaling/p/17680894.html

相关文章

  • 金蝶云星空表结构删除字段存储过程设计
    业务背景:数据库模型设计时命名错误,点击了保存,重新换了正确的字段后错误的数据字段还存储数据库,且删除字段前要先查询约束并删除约束后才能删除字段成功。每一次错误都是一次重复工作量。 解决方案:设计一个存储过程,传入表名和字段名,先查询该字段约束,存在先删除,然后再删除字段......
  • 【IEEE802】IEEE802协议组简述
    IEEE802协议概览协议说明功能IEEE802IEEE802是一种物理协议,因为有很多子协议,把这些协议汇集在一起就叫802协议集IEEE802.1x基于端口的访问控制协议能够在利用IEEE802局域网优势的基础上提供一种对连接到局域网的用户进行认证和授权的手段,达到了接受合法用户接......
  • 高并发过程中遇到的各项名词解释
    QPS(最大/最小/平均)QueriesPerSecond是每秒查询率,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,即每秒的响应请求数,也即是最大吞吐能力。QPS(TPS)=并发数/平均响应时间TPS(最大/最小/平均)TransactionsPerSeco......
  • 【Python 自动化】自媒体剪辑第一版·思路简述与技术方案
    大家都知道我主业是个运维开发(或者算法工程师),每天时间不多,但我又想做自媒体。然后呢,我就想了个方案,每天起来之后写个短视频的脚本,包含一系列图片和文字,然后上班的时候给它提交到流水线上跑,下班之前就能拿到视频,然后往各大平台上一传,是不是挺美滋滋的。我和我之前的合伙人一说,他就......
  • python 学习过程1
    第一天可以用加号连接字符串:利用反斜杠闭合单引号防止和后面的单引号闭合导语句错误。变量赋值之后,重复利用:先用greet(招呼)作为变量,然后你好吃了么作为赋值这里保留了中文打招呼和英文打招呼目的就是为了防止赋值丢失变量取名规则:文字、数字、下划线组成。(zhang_3)不能有下划线之外......
  • 4.go语言复合类型简述
    目录1.本章前瞻2.来自leetcode的例题描述分析题解3.复合类型新版本的变化3.1string和[]byte的高效转化3.2内置函数clear4.复合类型概述4.1切片4.2映射4.3字符串4.3.1字符串的底层机构4.3.2string和[]byte的转化6.下一篇1.本章前瞻很好,经过很长的时间,你终于来到go语......
  • mysql 创建定时器,每天晚上1点钟调用存储过程proc_task
    在MySQL中,你可以使用事件调度器(EventScheduler)来创建定时器,以在指定时间自动执行存储过程。以下是在每天晚上1点钟调用存储过程proc_task的示例:首先,确保MySQL事件调度器已经启用。如果尚未启用,可以在MySQL客户端中执行以下命令:SETGLOBALevent_scheduler=ON;然后,创......
  • 网络规划设计师真题解析--交换机(一)(STP选择过程)
    下图所示是一个园区网的一部分,交换机A和B是两台接入层设备,交换机C和D组成核心层,交换机E将服务器群连接至核心层。如图所示,(2014年真题)如果采用默认的STP设置和默认的选举过程,其生成树的最终结果为(1),ABCD这时候交换机B上的一台工作站,想要访问交换机E上的服务器的路径是(2),A.B-D-E......
  • mysql到达梦存储过程常见问题
    1.1 变量的使用createorreplaceproceduree_test()asbegin setstrsql='selectidinto@eidfromtest2orderbyidlimit1,10'; insertintotestselectid,namefromtest2whereidin(eid); setstst=strsql; executestst;end;变量需要提前定义cre......
  • CPU执行程序的过程
    CPU执行程序的过程目录CPU执行程序的过程前言/基础知识为了更好的分析程序的执行过程,我们还需要了解一下基础的计算机硬件信息在执行指令前,我们还需要认识一下CPU中的重要部件:寄存器。特殊寄存器StackPointerregister(SP)LinkRegister(LR)ProgramCounter(PC)WordZeroRegister(W......