spring整套源码系列之【MVC关键源码】
2024-04-10 18:46:00 0 举报
spring整套源码系列之【MVC关键源码】
作者其他创作
大纲/内容
//初始化我们web上下文对象的 用于文件上传下载的解析器对象\t\tinitMultipartResolver(context);
return handler;
拦截器
这里也就是循环所有的HandlerMapping处理器映射器去匹配我们的请求地址,看谁符合(里面会有个HandlerInterceptor拦截器通过路径匹配本次请求是否对应),符合的话就创建对应的执行器链。【为何会有多个处理器映射器呢?比如我们通过@GetMapping注解的控制器跟其他方式的是不同的处理方式的,如果是@GetMapping的会找到RequestMappingHanlderMapping,而这个类的初始化方法又会把我们的@RequestMapping注解信息和方法映射对象保存到我们的 *路径映射注册表中】而且有一个匹配上了就直接返回执行器链了
synchronized (mutex)
return
preHandle:在控制器方法执行之前执行
为我们的invocableMethod(ServletInvocableHandlerMethod)设置参数解析器对象invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
finally
循环我们的系统配置配置的for (HandlerAdapter ha : this.handlerAdapters)
获取当前请求的session对象\t\t\tHttpSession session = request.getSession(false);
这个判断很简单的,无非就是判断我们的处理器(控制器)是不是实现了某些接口,这里也就是说我们使用不同的方式写的控制器,会有不同的处理器适配器去调用
否:找不到继续下一个HandlerMapping
尝试从缓存中加载我们的Controller中的标注了@InitBinder注解的方法\t\tSet<Method> methods = this.initBinderCache.get(handlerType);
try
检查是否支持我们的请求方法
是:找到了
将前面创建的WebDataBinderFactory设置到ServletInvocableHandlerMethod中\t\t\tinvocableMethod.setDataBinderFactory(binderFactory);
否
初始化我们的spring mvc九大组件initStrategies(ApplicationContext context)#DispatcherServlet
return 处理器执行链
是
异步的请求处理,所谓的异步,指的是当前请求会将Controller中封装的业务逻辑放到一个线程池中进行调用,待该调用有返回结果之后再返回到response中【不贴了,太细了】
获取到锁
//检查我们的请求对象\t\tcheckRequest(request);
因为锁是通过 synchronized 是 JVM 进程级,所以在分布式环境下,无法达到同步相同 Session 的功能
initRequestToViewNameTranslator(context);
创建我们的数据绑定器工厂 return createDataBinderFactory(initBinderMethods);
return 处理器(控制器)适配器
这里最终也就是调用到了我们的控制器,然后我们控制器就返回ModelAndView对象
为当前session生成一个唯一的可以用于锁定的key\t\t\t\tObject mutex = WebUtils.getSessionMutex(session);
return ModeAndView
这里我们都没有配置的
return ha;
service()#DispatcherServlet
获取我们数据绑定器工厂WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
catch
支持
postHandle:在控制器方法执行之后执行
//初始化我们的HandlerMapping initHandlerMappings(context);
初始化
一开始缓存是没有的methods == null
不支持继续循环找
判断是否能找到handler != null
initFlashMapManager(context);
循环遍历我们所有的handlerMappings对象for (HandlerMapping hm : this.handlerMappings)
依次循环调用我们的HandlerMapping的getHandler方法进行获取HandlerExecutionChainhandler = hm.getHandler(request);
根据Handler选择我们的HandlerAdpater对象,默认是@RequestMappingHandlerAdapter对象HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
设置ParameterNameDiscoverer,该对象将按照一定的规则获取当前参数的名称\t\t\tinvocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
循环我们容器中的拦截器对象
判断当前的HandlerAdapter是否支持当前的handlerha.supports(handler)
一直执行完拦截器,如果都没有return fasle 就返回true去开始执行处理器
从我们当前的请求中推断出我们的HandlerExecuteChain 处理器执行链对象mappedHandler = getHandler(processedRequest);
在xml中有配置HandlerMapping(处理器映射器)。在本类中的initHandlerMappings()方法为我们的DispatcherServlet类初始化赋值我们的handlerMappings集合
return false;
//初始化我们web上下文对象用于处理国际化资源的\t\tinitLocaleResolver(context);
检查是否需要session
把全局的initBinder注解跟局部的都放到initBinderMethods中去
检查request对象 判断我们的请求是不是文件上传的请求processedRequest = checkMultipart(request);
清除文件上传时候生成的临时文件cleanupMultipart(processedRequest);
获取我们的HandlerMethod(控制器)的class类型 Class<?> handlerType = handlerMethod.getBeanType();
将handlerMethod封装为一个ServletInvocableHandlerMethod对象,该对象用于对当前request的整体调用流程进行了封装ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
//获取我们容器中的所有拦截器对象\t\tHandlerInterceptor[] interceptors = getInterceptors();
这个handlerMethod就是我们的控制器实例
以@RequestMapping注解方法的为例handleInternal()#RequestMappingHandlerAdapter
tomcat在处理用户请求的时候会调用到web.xml中配置的前端控制器DispatcherServlet的service方法
doService#DispatcherServlet
判断我们spring web容器中配置的所有的handlerMapping集合对象this.handlerMappings != null
拦截器链
真的的调用我们的目标方法return doInvoke(args);
//给DispatcherSerlvet的ViewResolvers处理器\t\tinitViewResolvers(context);
//实例化我们处理器异常解析器对象\t\tinitHandlerExceptionResolvers(context);
判断当前是否需要支持在同一个session中只能线性地处理请求。默认为falsethis.synchronizeOnSession
入口
//实例化我们的HandlerAdapters\t\tinitHandlerAdapters(context);
session != null
//主题解析器对象初始化\t\tinitThemeResolver(context);
这个方法里面就不去看了,要看也可以,不过没必要吧,也不难
判断我们spring web容器中配置的所有处理器适配器是否为空this.handlerAdapters != null
0 条评论
下一页