FlashMap用于在页面redirect时传递参数。
FlashMap简单来说就是一个HashMap,内部使用LinkedMultiValueMap保持数据。FlashMap还保持有跳转的目标url。一个session中会保持多个FlashMap.
看一下FlashMapManager的定义
public interface FlashMapManager {
//从session中获取flashMap
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
//将falshMap保存到session中
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}
FlashMapManager的继承关系
AbstractFlashMapManager中retrieveAndUpdate的实现,很简单,就是从session中获取FlashMap。
@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);
}
saveOutputFlashMap方法的实现。
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);
if (logger.isDebugEnabled()) {
logger.debug("Saving FlashMap=" + flashMap);
}
//设置有效期,默认值是180秒
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);
}
} ·
DispatcherServlet的doService方法对FlashMap的使用。
@Override
protected 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);
.......
}