之前两篇博客springMVC源码分析--视图View(一)springMVC源码分析--视图AbstractView和InternalResourceView(二)中我们已经简单的介绍了View相关的知识,接下来我们介绍一个比较常用的RedirectView,顾名思义RedirectView是用于页面跳转使用的。

跳转的示例:

@RequestMapping("/index")
	public String index(Model model,RedirectAttributes attr){
		attr.addAttribute("attributeName", "attributeValue");
		model.addAttribute("book", "金刚经");
		model.addAttribute("description","不擦擦擦擦擦擦擦车"+new Random().nextInt(100));
		model.addAttribute("price", new Double("1000.00"));
		model.addAttribute("attributeName1", "attributeValue1");
		//跳转之前将数据保存到book、description和price中,因为注解@SessionAttribute中有这几个参数
		return "redirect:get.action";
	}

返回的值为“redirect:get.action”,这样在处理之后我们会看到浏览器会跳转到get.action中,首先我们需要了解请求的跳转会在浏览器中修改请求链接,这样跳转的请求和原请求就是两个不相干的请求,跳转的请求会丢失掉原请求的中的所有数据,一般的解决方法是将原请求中的数据放到跳转请求的链接中这样来获取数据。接下来我们看看springMVC的RediectView所做的处理,让我们不用关心原请求中的值问题。

首先当返回值为"redirect:get.action"时,会调用ViewNameMethodReturnValueHandler的handleReturnValue方法,判断是否是跳转页面,设置跳转标记

ViewNameMethodReturnValueHandler中的实现如下:

@Override
	public void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

		if (returnValue instanceof CharSequence) {
			String viewName = returnValue.toString();
			mavContainer.setViewName(viewName);
			//用于判断是否是跳转页面 redirect
			if (isRedirectViewName(viewName)) {
				mavContainer.setRedirectModelScenario(true);
			}
		}
		else if (returnValue != null){
			// should not happen
			throw new UnsupportedOperationException("Unexpected return type: " +
					returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
		}
	}

当判断页面是跳转页面是ViewResolver生成的View对象是RedirectView,这样就可以实现页面跳转工作了。

接下来我们看看在RedirectView中所做的操作,最终的实现是在renderMergedOutputModel中完成实现的,这边需要实现的机制是在连接重定向时数据会丢失,这样使用FlashMap将数据保存起来作为重定向后的数据使用。

@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);
			if (flashMapManager == null) {
				throw new IllegalStateException("FlashMapManager not found despite output FlashMap having been set");
			}
			//将数据保存起来,作为跳转之后请求的数据使用
			flashMapManager.saveOutputFlashMap(flashMap, request, response);
		}
		//重定向操作
		sendRedirect(request, response, targetUrl, this.http10Compatible);
	}

简单来说RedirectView实现了链接的重定向,并且将数据保存到FlashMap中,这样在跳转后的链接中可以获取一些数据。

springMVC源码分析--页面跳转RedirectView(三)的更多相关文章

  1. springMVC源码分析--拦截器HandlerExecutionChain(三)

    上一篇博客springMVC源码分析--HandlerInterceptor拦截器调用过程(二)中我们介绍了HandlerInterceptor的执行调用地方,最终HandlerInterceptor ...

  2. springMVC源码分析--FlashMap和FlashMapManager重定向数据保存

    在上一篇博客springMVC源码分析--页面跳转RedirectView(三)中我们看到了在RedirectView跳转时会将跳转之前的请求中的参数保存到fFlashMap中,然后通过FlashMa ...

  3. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

  4. springMVC源码分析--视图View(一)

    之前的博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们已经介绍了数据返回值的处理,在博客springMVC源码分析--ViewResolver视图解析器( ...

  5. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

  6. springMVC源码分析--视图AbstractView和InternalResourceView(二)

    上一篇博客springMVC源码分析--视图View(一)中我们介绍了简单介绍了View的结构实现及运行流程,接下来我们介绍一下View的实现类做的处理操作. AbstractView实现了rende ...

  7. SpringMVC源码分析6:SpringMVC的视图解析原理

    title: SpringMVC源码分析6:SpringMVC的视图解析原理 date: 2018-06-07 11:03:19 tags: - SpringMVC categories: - 后端 ...

  8. [心得体会]SpringMVC源码分析

    1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...

  9. 8、SpringMVC源码分析(3):分析ModelAndView的形成过程

    首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...

随机推荐

  1. Python基础【day01】:Hello World程序(二)

    本节内容 安装 Hello World程序 变量 一.Python安装 windows 1 2 3 4 5 6 7 1.下载安装包     https://www.python.org/downloa ...

  2. Hbase记录-Hbase shell使用

    HBase Shell HBase包含可以与HBase进行通信的Shell. HBase使用Hadoop文件系统来存储数据.它拥有一个主服务器和区域服务器.数据存储将在区域(表)的形式.这些区域被分割 ...

  3. oracle中rownum和rowid的区别【转】

    rownum和rowid的区别总括: rownum和rowid都是伪列,但是两者的根本是不同的. rownum是根据sql查询出的结果给每行分配一个逻辑编号,所以你的sql不同也就会导致最终rownu ...

  4. 源码分析之CountDownLatch

    https://www.cnblogs.com/leesf456/p/5406191.html

  5. 由-webkit-transform-style:preserve-3d;所想

    看一个用css3写幻灯片的demo用到了这么几个属性 .demo{ -webkit-transform-style:preserve-3d; -webkit-perspective:800px; -w ...

  6. u-boot移植(七)---代码修改---存储控制器

    一.CPU访问芯片的条件 CPU通过访问存储控制器,来读取外部设备的数据. CPU想访问一个芯片,需要如下条件(配置信息): 地址线 数据线:8位/16位/32位数据宽度 时钟/频率 其他芯片相关的特 ...

  7. C# 简单线程实例

    1.简单线程实例 以及委托(同步委托.异步委托) using System; using System.Collections.Generic; using System.Linq; using Sy ...

  8. sql 把多列内容合并

    这个语句不完整.应该是这样:stuff(select ',' + fieldname  from tablename for xml path('')),1,1,'') as ’别名‘这一整句的作用是 ...

  9. 交叉熵的数学原理及应用——pytorch中的CrossEntropyLoss()函数

    分类问题中,交叉熵函数是比较常用也是比较基础的损失函数,原来就是了解,但一直搞不懂他是怎么来的?为什么交叉熵能够表征真实样本标签和预测概率之间的差值?趁着这次学习把这些概念系统学习了一下. 首先说起交 ...

  10. 第18月第20天 tensorflow安装

    1. # Mac OS X $ sudo easy_install pip # Mac OS X, CPU only: $ sudo easy_install --upgrade six $ sudo ...