研究这个问题的意义是什么?该不会又是面试造火箭吧?
不,我想知道controller里的参数解析在哪里做的,为什么它能帮我们转为为bean
带着问题去找答案,过程如下:(springboot)
1.发送请求 /login
(1)域名解析。请求的URL是用域名标识的,比如taobao.com这 样,而HTTP网络通信需要得到IP地址才能建立连接,所以先要进行域名解析,访问域名解析服 务器DNS,得到域名的IP地址。
(2)经过CDN服务器的IP地址(Content Delivery Network,即内容分发网络)
cdn全称内容分布网络,就是将网站发布内容提前发送到距离用户最近的网络节点,这样用户上网就可以就近取得所需的内容,缩短用户访问网站的时间、提高访问成功率,保护源头网站不受攻击,解决了因为地域、带宽、运营商等问题,而造成用户访问网站延迟高或者无法访问,最终目标是提高用户上网体验,降低延迟,提升网速。
(3)经过微服务网关、负载均衡服务器
网关的基本功能: 智能路由:接收外部一切请求,并转发到后端的对外服务open-service上去; 注意:我们只转发外部请求,服务之间的请求不走网关。
(4)具体的应用服务器
2. servlet接收到请求
类名.方法名:DispatcherServlet.doDispatch()
3.找到映射器mappedHandler
类名.方法名: DispatcherServlet.doDispatch
mappedHandler = this.getHandler(processedRequest);
-----------------关于映射器-----------------------------
handlerMappings 是一个list存着:RequestMappingHandleMapping、WelcomPageHandleMapping等共5个映射列表
找到需要调用的那个controller对应的 handler
HandlerExecutionChain handler = mapping.getHandler(request);
最后我们返回的是RequestMappingHandleMapping里面对应的需要调用的controller
-----------------关于映射器 -----------------------------
4.找到适配器HandlerAdapter
类名.方法名:DispatcherServlet.doDispatch
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
-----------------关于映射器--------------------
通过上一步的HandlerExecutionChain对象,执行mappedHandler.getHandler()
可以得到Handler也就是HandleMethod对象
handlerAdapters 适配器列表包括RequestMappingHandlerAdapter、HttpRequestHandlerAdapter等共4个适配器
最后我们返回的是RequestMappingHandlerAdapter这个适配器
-----------------关于映射器--------------------
疑问1:为什么需要适配器?
答:映射器已经包含了controller信息,那么直接调用不就行了,为什么需要适配器?
很简单,映射器都分多个存储, 说明有不同类型的处理逻辑,那么就需要不同的适配器来处理不同的逻辑。 一般的请求对应的映射器是RequestMappingHandleMapping,适配器是RequestMappingHandlerAdapter。
5.调用handle准备执行controller
类名.方法名:DispatcherServlet.doDispatch
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
6.调用前准备
参数解析,,找到了!!!!!!!!!!!!参数解析是在这里开始做的
类名.方法名:InvocableHandlerMethod.getMethodArgumentValues
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
代码跟进
类名.方法名:AbstractNamedValueMethodArgumentResolver.resolveArgument
Object arg = this.resolveName(resolvedName.toString(), nestedParameter, webRequest);
代码跟进:获取参数值
类名.方法名:RequestParamMethodArgumentResolver.resolveName
String[] paramValues = request.getParameterValues(name);
代码跟进:调用controller
类名.方法名:InvocableHandlerMethod.invokeForRequest
this.doInvoke(args);
总结:
到此,就从用户请求到外围的转发,再到具体的应用服务器,再到servlet接收,然后到spring里的映射器、适配器,然后是参数解析准备工作,最后调用controller具体的方法。