FlashMapManager
public interface FlashMapManager {
@Nullable
FlashMap retrieveAndUpdate(HttpServletRequest var1, HttpServletResponse var2);
void saveOutputFlashMap(FlashMap var1, HttpServletRequest var2, HttpServletResponse var3);
}
结构图:
可以看出结构图非常简单,抽象类采用模板模式定义整个流程,具体实现类用SessionFlashMapManager通过模板方法提供了具体操作FlashMap的功能。
功能说明:
- 实际的Session中保存的FlashMap是List<FlashMap>类型,也就是说一个Session可以保存多个FlashMap,一个FlashMap保存着一套Redirect转发所传递的参数;
- FlashMap继承自HashMap,除了用于HashMap的功能和设置有效期,还可以保存Redirect后的目标路径和通过url传递的参数,这两项内容主要用来从Session保存的多个FlashMap中查找当前的FalshMap。
1.AbstractFlashMapManager
1.1 保存FlashMap的方法
public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
if (!CollectionUtils.isEmpty(flashMap)) {
//首先对flashMap中转发的地址和参数进行编码,这里的request主要是用来获取当前的编码
String path = this.decodeAndNormalizePath(flashMap.getTargetRequestPath(), request);
flashMap.setTargetRequestPath(path);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Saving FlashMap=" + flashMap);
}
//设置过期时间,默认值是180秒
flashMap.startExpirationPeriod(this.getFlashMapTimeout());
用于获取互斥变量,是模板方法,如果子类返回不为null则同步执行,否则不需要同步
Object mutex = this.getFlashMapsMutex(request);
if (mutex != null) {
synchronized(mutex) {
//取回保存的flashMap,如果没有则新建一个
List<FlashMap> allFlashMaps = this.retrieveFlashMaps(request);
List<FlashMap> allFlashMaps = allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList();
((List)allFlashMaps).add(flashMap);
//将添加完的list<FalshMap>更新到存储介质中去,是模板方法,由子类实现
this.updateFlashMaps((List)allFlashMaps, request, response);
}
} else {
List<FlashMap> allFlashMaps = this.retrieveFlashMaps(request);
List<FlashMap> allFlashMaps = allFlashMaps != null ? allFlashMaps : new LinkedList();
((List)allFlashMaps).add(flashMap);
this.updateFlashMaps((List)allFlashMaps, request, response);
}
}
}
1.1.2 子类的模板方法实现
public class SessionFlashMapManager extends AbstractFlashMapManager {
private static final String FLASH_MAPS_SESSION_ATTRIBUTE = SessionFlashMapManager.class.getName() + ".FLASH_MAPS";
public SessionFlashMapManager() {
}
@Nullable
protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {
HttpSession session = request.getSession(false);
return session != null ? (List)session.getAttribute(FLASH_MAPS_SESSION_ATTRIBUTE) : null;
}
protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) {
WebUtils.setSessionAttribute(request, FLASH_MAPS_SESSION_ATTRIBUTE, !flashMaps.isEmpty() ? flashMaps : null);
}
protected Object getFlashMapsMutex(HttpServletRequest request) {
return WebUtils.getSessionMutex(request.getSession());
}
}
1.2 retrieveAndUpdate方法
取回FlashMap并更新,这里会在取回的时候删除掉匹配的flashMap,并且会在每次取回的时候都会判断flashMap是否过期,然后过期的都会删除。
public final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {
//从存储介质session中获取list<FlashMap>,模板方法,子类实现
List<FlashMap> allFlashMaps = this.retrieveFlashMaps(request);
if (CollectionUtils.isEmpty(allFlashMaps)) {
return null;
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Retrieved FlashMap(s): " + allFlashMaps);
}
//检查过期的flashMap,并将那他们设置到mapsToRemove
List<FlashMap> mapsToRemove = this.getExpiredFlashMaps(allFlashMaps);
//获取与当前request匹配的FlashMap,并设置到match中
FlashMap match = this.getMatchingFlashMap(allFlashMaps, request);
//如果有匹配的则将其添加到mapsToRemove,待下面删除
if (match != null) {
mapsToRemove.add(match);
}
//删除mapsToRemove中保存的变量
if (!mapsToRemove.isEmpty()) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Removing FlashMap(s): " + mapsToRemove);
}
Object mutex = this.getFlashMapsMutex(request);
if (mutex != null) {
synchronized(mutex) {
allFlashMaps = this.retrieveFlashMaps(request);
if (allFlashMaps != null) {
allFlashMaps.removeAll(mapsToRemove);
this.updateFlashMaps(allFlashMaps, request, response);
}
}
} else {
allFlashMaps.removeAll(mapsToRemove);
this.updateFlashMaps(allFlashMaps, request, response);
}
}
return match;
}
}