springMVC源码分析--FlashMap和FlashMapManager重定向数据保存
来源:互联网 发布:知柏地黄丸一般吃多久 编辑:程序博客网 时间:2024/04/29 20:59
在上一篇博客 springMVC源码分析--页面跳转RedirectView(三)中我们看到了在RedirectView跳转时会将跳转之前的请求中的参数保存到fFlashMap中,然后通过FlashManager保存起来。
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); }
接下来我们分别认识一下FlashMap和FalshMapManager
FlashMapManager是一个接口,定义了保存FlashMap和获取FlashMap的方法。
public interface FlashMapManager {//从session中获取flashMapFlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);//将falshMap保存到session中void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);}两个实现方法都在AbstractFlashMapManager抽象方法中:
saveOutputFlashMap方法实现如下
@Overridepublic final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {if (CollectionUtils.isEmpty(flashMap)) {return;}String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request);flashMap.setTargetRequestPath(path);if (logger.isDebugEnabled()) {logger.debug("Saving FlashMap=" + flashMap);}flashMap.startExpirationPeriod(getFlashMapTimeout());Object mutex = getFlashMapsMutex(request);if (mutex != null) {synchronized (mutex) {List<FlashMap> allFlashMaps = retrieveFlashMaps(request);allFlashMaps = (allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList<FlashMap>());allFlashMaps.add(flashMap);//flashMap是在子类SessionFlashManager中updateFlashMaps(allFlashMaps, request, response);}}else {List<FlashMap> allFlashMaps = retrieveFlashMaps(request);allFlashMaps = (allFlashMaps != null ? allFlashMaps : new LinkedList<FlashMap>());allFlashMaps.add(flashMap); //flashMap是在子类SessionFlashManager中updateFlashMaps(allFlashMaps, request, response);}}updateFlashMaps方法的实现机制就是将数据保存的请求的Session中,这样跳转后的请求可以从Session中获取数据,并且所有的实现都保存在同一个Session中,为了防止不同重定向请求的数据相互影响,这边有锁进行处理控制。
@Overrideprotected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) {WebUtils.setSessionAttribute(request, FLASH_MAPS_SESSION_ATTRIBUTE, (!flashMaps.isEmpty() ? flashMaps : null));}
retrieveAndUpdate获取FlashMap的实现如下:
@Overridepublic final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {List<FlashMap> allFlashMaps = retrieveFlashMaps(request);........}retrieveFlashMaps中的实现机制就是从Session中获取数据
@Override@SuppressWarnings("unchecked")protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {HttpSession session = request.getSession(false);return (session != null ? (List<FlashMap>) session.getAttribute(FLASH_MAPS_SESSION_ATTRIBUTE) : null);}
当重定向的请求在浏览器中重定向之后会进入的DispatcherServlet的doService方法
@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {........//从Session中获取保存的FlashMap中的值FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}//将值保存到request中。这样就不需要通过浏览器跳转组装链接来传递参数了request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);.......}
FlashMap简单来说就是一个HashMap,用于数据保存。
public final class FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {private String targetRequestPath;private final MultiValueMap<String, String> targetRequestParams = new LinkedMultiValueMap<String, String>(4);private long expirationTime = -1;public void setTargetRequestPath(String path) {this.targetRequestPath = path;}public String getTargetRequestPath() {return this.targetRequestPath;}public FlashMap addTargetRequestParams(MultiValueMap<String, String> params) {if (params != null) {for (String key : params.keySet()) {for (String value : params.get(key)) {addTargetRequestParam(key, value);}}}return this;}public FlashMap addTargetRequestParam(String name, String value) {if (StringUtils.hasText(name) && StringUtils.hasText(value)) {this.targetRequestParams.add(name, value);}return this;}public MultiValueMap<String, String> getTargetRequestParams() {return this.targetRequestParams;}public void startExpirationPeriod(int timeToLive) {this.expirationTime = System.currentTimeMillis() + timeToLive * 1000;}public void setExpirationTime(long expirationTime) {this.expirationTime = expirationTime;}public long getExpirationTime() {return this.expirationTime;}public boolean isExpired() {return (this.expirationTime != -1 && System.currentTimeMillis() > this.expirationTime);}@Overridepublic int compareTo(FlashMap other) {int thisUrlPath = (this.targetRequestPath != null ? 1 : 0);int otherUrlPath = (other.targetRequestPath != null ? 1 : 0);if (thisUrlPath != otherUrlPath) {return otherUrlPath - thisUrlPath;}else {return other.targetRequestParams.size() - this.targetRequestParams.size();}}@Overridepublic boolean equals(Object other) {if (this == other) {return true;}if (!(other instanceof FlashMap)) {return false;}FlashMap otherFlashMap = (FlashMap) other;return (super.equals(otherFlashMap) &&ObjectUtils.nullSafeEquals(this.targetRequestPath, otherFlashMap.targetRequestPath) &&this.targetRequestParams.equals(otherFlashMap.targetRequestParams));}@Overridepublic int hashCode() {int result = super.hashCode();result = 31 * result + ObjectUtils.nullSafeHashCode(this.targetRequestPath);result = 31 * result + this.targetRequestParams.hashCode();return result;}@Overridepublic String toString() {return "FlashMap [attributes=" + super.toString() + ", targetRequestPath=" +this.targetRequestPath + ", targetRequestParams=" + this.targetRequestParams + "]";}}
1 0
- springMVC源码分析--FlashMap和FlashMapManager重定向数据保存
- SpringMVC源代码学习外传(二)如何在重定向时传递参数&FlashMap
- SpringMVC 转发和重定向
- springmvc转发和重定向
- SpringMVC重定向视图RedirectView小分析
- SpringMVC重定向视图RedirectView小分析
- SpringMVC重定向视图RedirectView小分析
- SpringMVC中重定向数据转发
- springMVC 请求转发和重定向(RedirectAttributes)
- SpringMVC-请求转发和重定向
- 关于SpringMVC重定向和Json字符串
- SpringMVC中的转发和重定向
- SpringMVC 结果的转发和重定向
- SpringMvc中的转发和重定向
- springmvc里的转发和重定向
- SpringMVC中的转发和重定向
- springmvc转发和重定向(十一)
- springmvc中的转发和重定向
- 含UGUI的预制怎样添加到canvas里
- LeetCode题解-3-Longest Substring Without Repeating Characters
- 售货员的难题
- CSU 1112——机器人的指令
- mysql_real_escape_string转变了哪些字符
- springMVC源码分析--FlashMap和FlashMapManager重定向数据保存
- 数字矩阵 动态规划
- ibatis总配置文件详解
- RT任务调度概览
- springMVC源码分析--页面跳转RedirectView(三)
- Solr入门之Lucene&Solr临近查询之SpanQuery
- Unity编程标准导引-Unity中的基本概念-2.1界面概览
- usaco4.2.1 Drainage Ditches
- POJ 3126-Prime Path(BFS-素数变换一位)