springmvc源码-调用
上篇博客主要记录了handlerMapping初始化时的一些笔记,这篇主要是调用过程的学习笔记
调用
在调用一个方法的时候,会通过HttpServlet、FrameworkServlet等进行调用,最终会调用到
org.springframework.web.servlet.DispatcherServlet#doDispatch
我们就从这个方法开始记录笔记
在开始之前,有几个概念,先总结说明一下,上篇博客有说到过,声明一个controller的三种方式,这三种方式在调用的时候,是由不同的handlerMapping和handlerAdapter来处理的
实现Controller接口通过BeanNameUrlHandlerMapping来处理通过SimpleControllerHandlerAdapter来处理通过SimpleControllerHandlerAdapter类中的方法来调用实现接口的目标类的方法实现HttpRequestHandler接口通过BeanNameurlHandlerMapping来处理通过HttpRequestHandlerAdapter来处理通过HttpRequestHandlerAdapter调用实现接口类的目标方法通过@Componenet注解通过RequestMappingHandlerMapping来处理通过RequestMappingHandlerAdappter来处理通过反射的方式来调用目标方法(org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal)
这是三种声明controller的方式对应的处理类和方式
下面是doDispatch()的部分代码
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;
}// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}
}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
我只截取了doDispatch()方法中的部分代码
handlerMapping
这里可以看到:mappedHandler = getHandler(processedRequest);
这个方法是根据request的url找到当前url对应的method是在哪个handlerMapping中存储的,找到了,就返回当前handlerMapping
我们通常所说的:通过url找到对应的handlerMapping就是根据url从map集合中找对应的handlerMapping,在查找的时候,会遍历所有的handlerMapping(spring自己的+程序员提供的),在哪个handlerMapping找到了,就返回哪个handlerMapping
这里不同的handlerMapping,是放在不同的map集合中存储的;在这个遍历之后,找到合适的handlerMapping之后,会将合适的handlerMapping包装成HandlerExecutionChain;
handlerAdapter
根据handlerMapping找合适的handlerAdapter,是指:判断当前的handler(handler我觉得可以简单理解为controller)需要用哪个handlerAdapter来处理;
实现Controller接口的类,需要SimpleControllerHandlerAdapter来处理,在SimpleControllerHandlerAdapter该类中,判断条件很简单:return handler instanceof Controller;
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#supports
@Override
public boolean supports(Object handler) {return (handler instanceof HttpRequestHandler);
}
对于HttpRequestHandlerAdapter来说,判断当前handler是否是HttpRequestHandler类型的
@Override
public boolean supports(Object handler) {return (handler instanceof HttpRequestHandler);
}
对于RequestMappingHandlerMapping来说
// 只有这里的handler是handlerMethod的实例,就可以了,后面的supportsInternal默认是返回true的
@Override
public final boolean supports(Object handler) {return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
springmvc提供的扩展点
所以这里:spring做的比较好,spring定义了handlerAdapter接口,分别声明了
// 这个方法是判断当前handlerAdapter是否支持handler的处理
boolean supports(Object handler);
//具体处理handler的方法
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
这样就给程序员提供了扩展的空间,程序员如果要自己扩展handlerAdapter,那只需要提供handlerAdapter的实现类即可,并且将自己实现的类告诉spring;spring本身的代码无需做改造,因为在判断使用哪个handlerAdapter的时候,会遍历所有的
调用目标方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
是真正来调用目标方法的入口
在调用的时候,如果是通过@Controller注解和@RequestMapping来声明的方法,是通过反射机制来调用的
如果是通过剩下两种方式声明的controller,是直接通过类型强转,调用实现类的方法的
ha.handler()方法其实调用的,就是handlerAdapter实现类中的handler()方法
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#handle@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {((HttpRequestHandler) handler).handleRequest(request, response);return null;
}
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#handle@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return ((Controller) handler).handleRequest(request, response);
}
这两个handlerAdapter的handler方法比较简单,都是直接进行了强转,然后调用相应的实现类中的方法
比较麻烦的是RequestMappingHandlerAdapter的handler方法
这里涉及到从request中取参数赋值,然后通过反射机制,调用method.invoke()方法完成调用
并且还会涉及到对返回值的处理:是通过流写出去?还是进行视图渲染、视图转发等;如果方法加了@ResponseBody注解,就会把返回值通过流的方式写出去;如果没有,那默认是按照modelAndView来进行视图的渲染和返回;
这种处理方式中,给参数赋值的这块逻辑我还在看,待学习之后,补充
springmvc源码-调用相关推荐
- SpringMVC源码系列:HandlerMapping
SpringMVC源码系列:HandlerMapping SpringMVC源码系列:AbstractHandlerMapping HandlerMapping接口是用来查找Handler的.在Spr ...
- SpringMVC源码阅读:过滤器
SpringMVC源码阅读:过滤器 目录 1.前言 2.源码分析 3.自定义过滤器 3.1 自定义过滤器继承OncePerRequestFilter 3.2 自定义过滤器实现Filter接口 4.过滤 ...
- SpringMVC源码分析(4)剖析DispatcherServlet重要组件
简单介绍了一个请求的处理过程, 简略描述了调用过程,并没有涉及过多细节,如url匹配,报文解析转换等. <SpringMVC源码分析(2)DispatcherServlet的初始化>:介绍 ...
- springMvc源码刨析笔记
springMvc源码刨析笔记 MVC 全名是 Model View Controller,是 模型(model)-视图(view)-控制器(controller) 的缩写, 是⼀种⽤于设计创建 We ...
- java注解返回不同消息,SpringMVC源码剖析5:消息转换器HttpMessageConverter与@ResponseBody注解...
转自 [SpringMVC关于json.xml自动转换的原理研究[附带源码分析]](https://www.cnblogs.com/fangj... 部分代码会放在我的的Github:https:// ...
- 筑基期第一式:SpringMVC源码解析
文章目录 SpringMVC源码解析 SPI机制 案例 SpringMVC中SPI的使用 初始化IOC容器与九大组件 初始化容器 初始化九大组件 小结 SpringMVC如何处理一个请求 doDisp ...
- springMVC源码分析--访问请求执行ServletInvocableHandlerMethod和InvocableHandlerMethod
在之前一篇博客中 springMVC源码分析--RequestMappingHandlerAdapter(五)我们已经简单的介绍到具体请求访问的执行某个Controller中的方法是在RequestM ...
- 简单直接让你也读懂springmvc源码分析(3.1)-- HandlerMethodReturnValueHandler
该源码分析系列文章分如下章节: springmvc源码分析(1)-- DispatcherServlet springmvc源码分析(2)-- HandlerMapping springmvc源码分析 ...
- SpringMVC源码剖析(五)-消息转换器HttpMessageConverter
概述 在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换,底层这种灵活的消息转换机制,就是Spring3.x中新 ...
- SpringMVC源码探究软件六合网站制作(一)----初始化源码
随着软件 , 开发技术的持续发展,框架技术层出不穷.还是那句话,任何框架技术都是对基础技术的封装.所以,真正要学好用好一个框架,研究其源码都是最直接最有效的途径. 随着Spring技术体系的强势发展, ...
最新文章
- flask_sqlalchemy 教程
- 英伟达奔驰共同发布自动驾驶系统,还自带停车功能
- 一款遥控器拆解之后可利用的元器件
- windows winrar 指令_【转】winrar命令行详解
- java一个源文件供一个程序_java02 Java源文件范例提供了一个布局合理的Java程序范例 - 下载 - 搜珍网...
- 阿里年薪40万老人简历:83岁精通网购,62岁会H5、PS
- Linux 抓包工具:tcpdump
- openlayers事件类型
- 华为哪个是鸿蒙,华为系统是鸿蒙还是安卓?有什么区别
- android 中解析json格式数据
- HashMap深度解析
- 使用jQuery+huandlebars遍历中if判断
- VMware14安装步骤
- matlab在常微分方程的应用,Matlab在常微分方程教学中的应用
- narwal机器人_Narwal云鲸扫地机器人扫拖彻底,用户用得更省心省力
- UE4 Slate四 SlateUI如何做动画
- 1、学生如何购买云服务器、域名(系列:个人博客搭建)
- sklearn基础篇(三)-- 鸢尾花(iris)数据集分析和分类
- anki服务端存储迁移
- NRF52832学习笔记(39)——设备信息服务(DIS)
热门文章
- 时间序列的分析和预测ARIMA
- 卷积神经网络CNN:Tensorflow实现(以及对卷积特征的可视化)
- 自动驾驶7-2 最终项目概述 Final Project Overview
- k-means 及其改进 数库
- DSSM核心思想是把查询文本(query)和内容文本(doc)映射到同维度的语义空间中, 以最优化查询文本和内容文本的语义向量之间的余弦相似度为目的
- 593. 有效的正方形
- 数中唯一只出现一次的数字
- 个税倒推收入的计算器_手把手教你做个税计算器(1)
- Spring boot initialization failed for https://start.spring.io
- 计算机图形学完整笔记(四):消隐