FlashMap 管理器接口,负责重定向时,保存参数到临时存储中
initFlashMapManager方法是其初始化的方法,同样在DispatcherServlet中
//DispatcherServlet.java private void initFlashMapManager(ApplicationContext context) { try { // 从环境中获得指定的bean this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class); if (logger.isTraceEnabled()) { logger.trace("Detected " + this.flashMapManager.getClass().getSimpleName()); } else if (logger.isDebugEnabled()) { logger.debug("Detected " + this.flashMapManager); } } catch (NoSuchBeanDefinitionException ex) { // We need to use the default. // 假如不存在就获取默认的内容 this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class); if (logger.isTraceEnabled()) { logger.trace("No FlashMapManager '" + FLASH_MAP_MANAGER_BEAN_NAME + "': using default [" + this.flashMapManager.getClass().getSimpleName() + "]"); } } }和其他组件初始化方法类似,不同的是他的默认值在catch中获取
保存FlashMap
AbstractFlashMapManager.java @Override public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) { if (CollectionUtils.isEmpty(flashMap)) { return; } // 首先对flashMap中转发的地址和参数进行编码,这里的request主要是用来获取当前的编码 String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request); flashMap.setTargetRequestPath(path); // 设置过期时间,默认值是180秒 flashMap.startExpirationPeriod(getFlashMapTimeout()); // 获得互斥变量的值 Object mutex = getFlashMapsMutex(request); // 不为空进行同步操作 加锁 if (mutex != null) { synchronized (mutex) { // 取回保存的flashMap,如果没有则新建一个CopyOnWriteArrayList List<FlashMap> allFlashMaps = retrieveFlashMaps(request); allFlashMaps = (allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList<>()); allFlashMaps.add(flashMap); // 更新FlashMap updateFlashMaps(allFlashMaps, request, response); } } // 不进行同步操作 else { List<FlashMap> allFlashMaps = retrieveFlashMaps(request); allFlashMaps = (allFlashMaps != null ? allFlashMaps : new LinkedList<>()); allFlashMaps.add(flashMap); updateFlashMaps(allFlashMaps, request, response); } } // 并没有实现,交给子类实现 protected abstract void updateFlashMaps( List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response);取回FlashMap并更新,每次取回的时候都会判断flashMap是否过期,然后过期的都会删除
AbstractFlashMapManager.java public final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) { // 获取list<FlashMap>,并没有实现,交给子类实现 List<FlashMap> allFlashMaps = retrieveFlashMaps(request); if (CollectionUtils.isEmpty(allFlashMaps)) { return null; } // 获得过期的FlashMap List<FlashMap> mapsToRemove = getExpiredFlashMaps(allFlashMaps); // 获得匹配的FlashMap,假如获取到则添加进mapsToRemove集合中 FlashMap match = getMatchingFlashMap(allFlashMaps, request); if (match != null) { mapsToRemove.add(match); } if (!mapsToRemove.isEmpty()) { // 取得互斥变量,决定使用同步和非同步 Object mutex = getFlashMapsMutex(request); if (mutex != null) { synchronized (mutex) { // 获得所有的FlashMap,然后从中移除到所有的mapsToRemove中的值,然后更新FlashMaps allFlashMaps = retrieveFlashMaps(request); if (allFlashMaps != null) { allFlashMaps.removeAll(mapsToRemove); updateFlashMaps(allFlashMaps, request, response); } } } else { allFlashMaps.removeAll(mapsToRemove); updateFlashMaps(allFlashMaps, request, response); } } return match; }AbstractFlashMapManager的子类,实现了关键的updateFlashMaps
从HTTP session保存指定的FlashMap
SessionFlashMapManager.java @Override protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) { // 核心就是把参数保存到了session中,通过参数进行置空或保存值 WebUtils.setSessionAttribute(request, FLASH_MAPS_SESSION_ATTRIBUTE, (!flashMaps.isEmpty() ? flashMaps : null)); }获得互斥的变量Mutex
SessionFlashMapManager.java protected Object getFlashMapsMutex(HttpServletRequest request) { return WebUtils.getSessionMutex(request.getSession()); }