github原文鏈接 https://github.com/DespairYoke/java-advance筐喳。創(chuàng)作不易剪个,請(qǐng)給個(gè)免費(fèi)的star信认,已表支持渣淤。
示例
@GetMapping(value = "hello")
public MyModelAndView index(String name, ModelAndView modelAndView) {
modelAndView.addObject("message",name);
modelAndView.setViewName("index");
return modelAndView;
}
返回值的處理
由于返回值類(lèi)型是ModelAndView,不是簡(jiǎn)單的字符串。這時(shí)返回值的處理不再使用ViewNameMethodReturnValueHandler
捻撑,而是使用了ModelAndViewMethodReturnValueHandler
處理的方式來(lái)處理磨隘。具體處理方法是
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
ModelAndView mav = (ModelAndView) returnValue;
String viewName = mav.getViewName();
mavContainer.setViewName(viewName);
mavContainer.setStatus(mav.getStatus());
mavContainer.addAllAttributes(mav.getModel());
}
這里只是簡(jiǎn)單的把視圖名(示例中的index)和mav中的model
(示例中的message)放入mavContainer
。那我們接著看下這個(gè)mavContainer
后續(xù)是如何處理顾患。
由執(zhí)行順序可以在RequestMappingHandlerAdapter
的invokeHandlerMethod
方法看到番捂,下一個(gè)對(duì)mavcontainer做處理的是getModelAndView
方法。
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
return mav;
}
可見(jiàn)mavContainer好像一個(gè)容器江解,把ModelAndView從返回值放入進(jìn)去设预,現(xiàn)在又取出來(lái)生成新的ModelAndView
。跟蹤代碼膘流,看下新的ModelAndView
又被何時(shí)處理絮缅。發(fā)現(xiàn)是在DispatcherServlet
的doDispatch
方法中的processDispatchResult
方法中進(jìn)行處理鲁沥。
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable MyHandlerExecutionChain mappedHandler, @Nullable MyModelAndView mv,Exception exception) throws Exception {
// 獲取視圖view
render(mv, request, response);
}
此時(shí)就調(diào)用了一個(gè)render
方法。
protected void render(MyModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
//獲取適合的view
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
view.render(mv.getModelInternal(), request, response);
}
-
resolveViewName
獲取適合的view
-
render
視圖渲染頁(yè)面耕魄。
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
-
createMergedOutputModel
創(chuàng)建了一個(gè)Map對(duì)象mergedModel
画恰,把model中的信息放入新對(duì)map對(duì)象mergedModel
中。 -
renderMergedOutputModel
是對(duì)新mapmergedModel
處理吸奴。
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
exposeModelAsRequestAttributes(model, request);
String dispatcherPath = prepareForRendering(request, response);
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
rd.forward(request, response);
}
- exposeModelAsRequestAttributes 是把model中的信息放入request中
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
model.forEach((modelName, modelValue) -> {
request.setAttribute(modelName, modelValue);
});
}
- prepareForRendering 根據(jù)示例中的
index
值允扇,找到對(duì)應(yīng)的jsp路徑。 - rd.forward 只是對(duì)request的轉(zhuǎn)發(fā)则奥。
總結(jié):spring只是把ModelandView
中的信息經(jīng)過(guò)一系列處理考润,最終放入了request
中,交給Servlet去處理读处。