看一段普通的代码,我们访问controller中的一个方法后,重定向到另外一个controller或者视图。

    @RequestMapping(params="method=index")
public ModelAndView index() {
RedirectView redirectView = new RedirectView("/Demo.do?method=index2", true, true);
ModelAndView mav = new ModelAndView(redirectView);
mav.addObject("attr1", "attr1Value");
mav.addObject("attr2", "attr2Value");
return mav;
}

浏览器的URL会变成http://localhost:8080/FuDeKang/Demo.do?method=index2&attr2=attr2Value&attr1=attr1Value

也就是说Spring会自定把model中的键值放入到URL当中,那么Spring是如何做到的呢,我么还来看ModelAndViewMethodReturnValueHandler这个类。

public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {

    public boolean supportsReturnType(MethodParameter returnType) {
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
} public void handleReturnValue(
Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception { if (returnValue == null) {
mavContainer.setRequestHandled(true);
return;
} ModelAndView mav = (ModelAndView) returnValue;
if (mav.isReference()) {
String viewName = mav.getViewName();
mavContainer.setViewName(viewName);
if (viewName != null && viewName.startsWith("redirect:")) {
mavContainer.setRedirectModelScenario(true);
}
}
else {
View view = mav.getView();
mavContainer.setView(view);
if (view instanceof SmartView) {
if (((SmartView) view).isRedirectView()) {
mavContainer.setRedirectModelScenario(true);
}
}
}
mavContainer.addAllAttributes(mav.getModel());
} }

其中最后一句是关键,首先modelandview当中的model数据全部放到ModelAndViewContainer 里面。

因为我们是重定向,所以无论如何底层最后产生的视图对象都是RedirectView实例,我们在看一下它的源码。

    /**
* Convert model to request parameters and redirect to the given URL.
* @see #appendQueryProperties
* @see #sendRedirect
*/
@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws IOException { String targetUrl = createTargetUrl(model, request); targetUrl = updateTargetUrl(targetUrl, model, request, response); FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
if (!CollectionUtils.isEmpty(flashMap)) {
UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build();
flashMap.setTargetRequestPath(uriComponents.getPath());
flashMap.addTargetRequestParams(uriComponents.getQueryParams());
} FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response); sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
}

其中  targetUrl = updateTargetUrl(targetUrl, model, request, response);  是拼接了URL的代码,最后调用sendRedirect做重定向。

最新文章

  1. 分布式学习系列【dubbo入门实践】
  2. 函数式 js 接口实现原理,以及 lodash/fp 模块
  3. C/C++入门---运算符
  4. c# 游戏策划配置工具
  5. c中的基本运算
  6. Android SDK 国内镜像
  7. EventBus初理解
  8. Ubuntu14.04 搭建 node.js 环境(Binaries方式)
  9. E-BOM和M-BOM的区别
  10. Linux系统Load average负载详细解释
  11. C#操作Office.word(一)
  12. La=LaULb (循环链表)
  13. Google浏览器的缓存文件过大(mega网站导致的)
  14. bzoj 2229: [Zjoi2011]最小割
  15. Emmet for Dreamweaver:HTML/CSS代码快速编写神器
  16. linux查看进程启动的时间点
  17. JS深拷贝/深克隆(面试用)
  18. 使用fakeroot模拟root权限执行程序(转)
  19. Haskell语言学习笔记(73)Existentials
  20. 2 URL的玩法

热门文章

  1. 机器学习---支持向量机(SVM)
  2. (LeetCode)用两个栈实现一个队列
  3. Windows键盘消息处理
  4. stm8 I/O口模式配置
  5. 查看mysql状态的常用命令
  6. 关于 f 散度
  7. nmap 端口扫描工具
  8. activiti设置流程变量
  9. [MeetCoder] Crossing Bridge
  10. Java设计模式之工厂模式的两种实现方式