【springboot】Servlet API参数解析(一)及√Model、Map类型源码分析(二)及自定义参数(三)

(二)是有关以下一些复杂参数类型的处理: 

(二)通过下面这个方法展示Model、Map等类型参数的源码分析:

在success方法中通过request获得“msg”的值这句,打断点。 

其实就是testParam方法请求的这几个对象需要我们留意分析:

而Map、Model、request都可以向request域中放数据。然后在sucess方法中通过request.getAttribute得到放在request域中的Map、Model等类型的数据。

依旧debug进入循环判断resolver的方法,查看parameter可以发现对应的方法及其参数类型:

依旧是逐个判断,按顺序得到对应我们三种参数的resolver匹配(三种supportsParameter方法):

(Map)在类中的该方法:

(Model)在类中的该方法: 

(request)(response)在类中的该方法略。

(印证了(二)中发现的处理多种不同的参数时采用不同的methodProcessor(不同的resolver)。)按照这个顺序解析参数——返回一个获得的resolver后(结束执行supportsParameter段逻辑),退回到原来的两个if判断处,再进入resolveArgument段逻辑:

        下面按照方法的参数顺序,依次匹配到Map类型(参数[0])、Model类型(参数[1])、Request和Response类型(参数[3]、参数[4]):

(1)首先是Map类型(参数[0]):

进入resolveArgument段逻辑: 

获得resolver不为null后调用对应resolver(这里是针对Map类型的)的resolveArgument方法: 

注意查看ModelAndViewContainer类型:

进入ModelAndViewContainer类,针对Map类型的参数,mavContainer.getModel得到的是:

因此一般使用defaultModel,对象是BindingAwareModelMap。而他们的关系是:

一方面得到这个BindingAwareModelMap不仅是Model,也是Map:

(2)接着判断第二个参数(parameter[1])——Model类型:

然后发现跟Map类型调用的resolveArgument方法都是一样的:

也是通过mavContainer.getModel取得model对象的值。

现在args数组的值从 变成了:

惊喜地发现两者是同一个对象(BindingAwareModelMap)。 

(3)Request、Response对象(参数[3]、参数[4]):过程略。

在return args;处打断点,直接放行到此处。args数组的值如下:

得到args包含四个参数后doInvoke就是执行目标controller的方法了,回到controller种的断点处: 

执行完controller后会返回到invokeAndHandle方法处的断点: 

返回值returnValue的值为:就要进行页面的转发处理。

且此时mavController已经存入Map和Model类型的两个参数:

(但是需要注意的是此时的view为null:,后文会再提到)

(无论怎样变换mavController都还是前文提到的同一个@7028的ModelAndViewContainer对象,而defaultModel是同一个@7232的BindingModelMap对象)

获得返回值后,returnValueHandler(返回值处理器)可以开始处理返回值:

*同理,returnValueHandler(返回值处理器)也有15种类型:

这个处理返回值的方法传入了返回值,返回值的类型,mavContainer(包含参数的值、信息)、我们的原生请求webRequest: 

进入handleReturnValue方法: 

继续进入handle.handleReturnValue方法:

 就是将返回值(字符串)存成viewName(视图名),将其存入mavContainer中。

现在可以更深刻地理解到ModelAndViewContainer(mavContainer)的含义——Model和View对象的容器。View是要返回的地址(——视图),Model就是我们到这个地址携带的数据

最后view的值也被添加到mavContainer中:(前文为null)

 

此时mavContainer包含我们请求所有的数据。

modelFactory可以帮助getModelAndView。进入getModelAndView方法:

getModelAndView方法告诉我们,执行完目标方法后由他来处理mavContainer(的内容):

①先进入updateModel方法,看他是如何更新mavContainer的:

更新model的绑定结果,就是得到ModelAndMap对象model中的数据(这里包含了前文的Model、Map对象)——遍历得到对应的key和value:

“绑定”这部分留到(三)自定义对象 那部分再详解。

回到getModelAndView方法中下部分,返回ModelAndView对象(mav):

完成ModelAndView对象的获取,完成请求处理。

A:一路回退到DispatcherServlet的doDispatch起始方法:,才真正完成ha.handle方法。

到这里我的mv为null。(需要重新debug,不知道哪里出了问题。。。)

B:请求处理完后执行applyPostHandle方法,进行拦截器(interceptors)的postHandle处理:

C:还需要处理派发结果(processDispatchResult方法): 

可以进入 processDispatchResult方法看一下是如何处理分发结果的:

此时的mv对象中的model是重新封装过的(@后数字不一样,不同对象): 

在processDispatchResult方法中继续向下执行,mv不为null,故进入render方法:

render方法-部分代码1
render方法部分代码-1

render一般是“渲染”的意思。 

mv.getViewName得到视图名viewName后,resolveViewName方法解析视图名,得到视图view。

 第二个参数model是Map类型的:,所以调用该方法得到view时需要先将mv(ModelAndView)中的model通过mv.getModelInternal得到:

evaluate  mv.getModelInternal的值,发现model就是我们的数据:

getModelInternal方法: 

进入resolveViewName方法,其中的viewResolver(视图解析器)解析viewName。

再进入viewResolver的resolveViewName方法: 

这里返回的bestView就是目标取得的view。

render方法-部分代码-2

 

进入render方法的核心方法: 

mergedModel是合并(merge)后的model。

得到mergedModel后返回render方法中: 

进行②准备响应(prepareResponse)和③渲染合并后输出的model(renderMergedOutputModel)。

renderMergedOutputModel是我们render渲染方法中的核心方法:

新版的getRequestToExpose方法: 

旧版的getRequestToExpose方法:  

返回一个原始的暴露请求(original)还是新的类型的。

故进入renderMergedOutputModel方法(InternalResourceView中):

关注到exposeModelAsRequestAttributes(核心方法)将model的数据(前面已提到过)暴露出来作为请求域的参数(attributes),(即在请求域中存取较容易??)。。。其实这是后面的视图解析器InternalResourceView的内容,这里不详述。

 进入exposeModelAsRequestAttributes方法:

因此我们可以知道:我们加在方法上的参数Model和Map都是一个东西,因为数据都放到model中,然后最后都会被加到请求域中(request.addAttribute)——>>看源码这么久的意义。 

注意:这里有一个自学的思路,就是找实现方法时,如果只找到接口的抽象方法,可以ctrl+h(idea中快捷键)查看他与子类的继承or接口的实现关系,找到接口方法的实现类,就可以找到目标实现方法。比如在寻找render方法时(指不走debug时),返回的是View接口,就可以找它的实现类AbstractView,找renderMergedOutputModel具体方法时可以找他的子类InternalResourceView(具体如下图):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值