假装看源码之springmvc (二) redirectAttributes是什么回事?


	/**
	 * 1、原始请求: /demo2/redirect
	 */
	@RequestMapping("/redirect")
	public String RedirecAttr(RedirectAttributes attr){
		attr.addAttribute("id", 1); //等于在重定向的请求链接中拼接参数。
		attr.addFlashAttribute("result", "成功");//可以直接在重定向的新请求返回到视图时,用${result}获取.
		return "redirect:/demo2/list";
	}
	
	/**
	 * 2、重定向的请求: 在浏览器显示的链接是 /demo2/list?id=1
	 */
	@RequestMapping("list")
	public String list(int id,String result, @ModelAttribute("result") String result2){
		System.out.println(id); //1  -->请求参数有id=1
		System.out.println(result); //null  -->请求参数没有result="成功"
		System.out.println(result2); //成功  
		return "/index"; //返回到页面,${result}的渲染结果是"成功"
	}

前言:从上面的demo中我们可以知道,请求1执行后,能把result="成功"的参数在重定向的请求,访问页面的时候直接用${result}得到。或者可以用@ModelAttribute(result)得到。这个场景在实际开发中用很频繁,比如操作了一个表单进行提交,而一般会重定向到一个页面进行展示结果提示,而这个过程中,一般都有带点参数的需求,当然直接在重定向的地址中显示是一个办法,而只要使用RedirectAttributes,一切都自动完成了。

    一、我们先不考虑这个工作具体是那个类完成的,一般spring框架你看到的类,并不是实际完成这个功能的类,所以想都不要想,redirectAttr其实就是一个model的子类,把重定向参数临时放入里面而已。至于大概的原理,用脚趾头想下,一个请求的参数能保留到另外一个请求,肯定是放到session中的。至于怎么放的。请看下面的分析。

    1.1 何时从redirectAttr里面取出FlashAttr的参数呢? 我们直接从HandlerAdpter执行完Handler后的过程分析,即在视图解析器解析之前,组装modelAndView之后的这个过程。

     

  1.2 这个过程只是把model(redirectAttributes)的重定向参数放人了,一个叫OutputFlashMap中,而再后面视图解析后,最终会把这个FlashMap添加到session中一个属性(是个list集合)中。那么下一个请求来的时候,在根据某些规则取出这一个flashmap。这个后面视图解析的过程调用链比较长,不具体演示。我们从下一个请求怎么获取flashMap开始看。

    

1.3从上面就可以看到在springmvc进行具体请求处理之前就会去找flashMap.设置到request中的属性中,并且会创建一个空的outFlashMap,就是1,2标记的(1)。我们只要具体研究retrieveAndUpdate方法即可!在这个之前,先研究下flashMap的结构,flashmapManager就是对flashmap的操作,等下断点进去看即可。(上面说的inFlashMap和outFlashMap都是一个类的对象,只是springmvc放入request域中的属性名叫in 和out 而已)

    

    1.4 flashMap就是个hashMap,但是它有过期时间,并且存了重定向的地址,这样在新的请求中,就可以对比是不是这个地址,来判断此session的请求是否找出这个flashMap。

二、具体取出flashMap的过程,即1.2中断点的方法。

    

扫描二维码关注公众号,回复: 2139016 查看本文章

2.1上面的过程很简单,就是从session中取出flashMap.然后判断过期的全部放入到一个mapToRemove。再匹配出合法的flashMap,最后把过期的和匹配的再取出的allFlashMaps中删除,并且更新回session中。上面的每个步骤都很简单,我们详细分析下如何匹配的即可。



2.2 上面图1,说明是可能匹配多个flashmap的,但是只取一个。从图2的匹配规则来说,在重定向这个区间类,基本只能匹配一个。图2,说明 /demo2 可以和/demo2/进行匹配的。而RequestParams是addAttribute过的id=1,即拼接的链接解析的请求参数要和flashMap中存的也进行对比下。(备注:requestParams即是存到FlashMap成员变量中的map,而前面说的addFlashAttr是存到它继承的map中的)

2.3 在上面的步骤执行完,就把取出的flashMap放入到request的IN_FLASHMAP参数中,供后面使用。剩余在视图解析的过程,应该还存在还有部分就是怎么放入到页面请求域,并移除session域中flashMap的操作(猜测的)。

猜你喜欢

转载自blog.csdn.net/shuixiou1/article/details/79681319