String attrName = entry.getKey();
SessionAttribute attr = entry.getValue();
if (attr.isModified()) {
String storeName = attr.getStoreName();
SessionStore store = attr.getStore();
if (isApplicableToCommit(store, commitHeaders)) {
StoreData data = mappings.get(storeName);
if (data == null) {
data = new StoreData(storeName, store);
mappings.put(storeName, data);
}
Map<String, Object> storeAttrs = data.attrs;
Object attrValue = attr.getValue();
// 特殊处理model,将其转换成store中的值。
if (attrValue instanceof SessionModel) {
attrValue = requestContext.getSessionConfig().getSessionModelEncoders()[0]
.encode((SessionModel) attrValue);
} else {
// 只检查非session model对象的modified状态
modified = true;
}
storeAttrs.put(attrName, attrValue);
attr.setModified(false); // 恢复modified状态,以防多余的警告信息
} else if (!commitHeaders) {
if (mayNotBeCommitted == null) {
mayNotBeCommitted = createLinkedHashMap();
}
StringBuilder buf = mayNotBeCommitted.get(storeName);
if (buf == null) {
buf = new StringBuilder();
mayNotBeCommitted.put(storeName, buf);
}
if (buf.length() > 0) {
buf.append(", ");
}
buf.append(attrName);
}
}
}
if (mayNotBeCommitted != null) {
for (Map.Entry<String, StringBuilder> entry : mayNotBeCommitted.entrySet()) {
String storeName = entry.getKey();
SessionStore store = requestContext.getSessionConfig().getStores().getStore(storeName);
String attrNames = entry.getValue().toString();
log.warn("The following attributes may not be saved in {}[id={}], because the response has already been committed: {}",
new Object[] { store.getClass().getSimpleName(), storeName, attrNames });
}
}
// 如果既没有参数改变(即没有调用setAttribute和removeAttribute),
// 也没有被清除(即没有调用invalidate和clear),并且isKeepInTouch=false,
// 则不提交了,直接退出。
if (!modified && !cleared && !requestContext.getSessionConfig().isKeepInTouch()) {
return;
}
// 对每一个store分别操作。
for (StoreData data : mappings.values()) {
data.store.commit(data.attrs, getId(), new StoreContextImpl(data.storeName));
clearingStores.remove(data.storeName); // 如果先clear后又设值,则一会儿不需要再进行clear,故清除clearing标记
}
// 假如invalidate和clear被调用,则检查剩余的store,通知它们清除当前的数据。
if (cleared) {
for (Iterator<String> i = clearingStores.iterator(); i.hasNext(); ) {
String storeName = i.next();
SessionStore store = requestContext.getSessionConfig().getStores().getStore(storeName);
if (isApplicableToCommit(store, commitHeaders)) {
Map<String, Object> storeAttrs = emptyMap();
store.commit(storeAttrs, sessionID, new StoreContextImpl(storeName));
i.remove(); // 清除clearing标记,以防重复clear
} else if (!commitHeaders) {
log.warn("Session was cleared, but the data in {}[id={}] may not be cleared, " +
"because the response has already been committed.", store.getClass().getSimpleName(), storeName);
}
}
}
}