一个简单的不依赖session的FlashMapManager

spring


发表于 2018-05-10 20:07


Spring mvc RedirectAttributes的背后是FlashMapManager在辛勤的工作,而SessionFlashMapManager则是唯一实现了FlashMapManager意志的男人。 SessionFlashMapManager会将FlashMap集合存储在session中,key为

org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS

但我认为这种单纯的向用户显示信息的行为并不需要session来实现,于是想借助Cookie来存储,在github上发现了一个实现:https://github.com/trecloux/spring-flash-cookie/blob/master/src/main/java/com/github/trecloux/flashcookie/CookieFlashMapManager.java 但它是将加密后的json串存储在了cookie中,然后通过解密还原的,这本身就需要一定的开销,另外存储的内容也可能会较大,影响传输,一番考虑之后,将信息对象依旧存储在服务器内存中,只是将获取该信息的ID存储到了客户端的cookie中,简单的实现如下:

public class CookieMemoryLinkFlashMapManager extends AbstractFlashMapManager {

	@Autowired
	private UrlHelper urlHelper;

	private static final String MESSAGE_ID = "messageId";
	private Map<String, List<FlashMap>> map = new ConcurrentHashMap<>();

	@Override
	protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {
		Cookie cookie = WebUtils.getCookie(request, MESSAGE_ID);
		if (cookie == null) {
			return null;
		}
		return map.get(cookie.getValue());
	}

	@Override
	protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) {
		Cookie cookie = WebUtils.getCookie(request, MESSAGE_ID);
		if (CollectionUtils.isEmpty(flashMaps)) {
			if (cookie != null) {
				map.remove(cookie.getValue());
				// setCookie(cookie, "", 0, response);
			}
		} else {
			String id = StringUtils.uuid();
			map.put(id, flashMaps);
			if (cookie == null) {
				cookie = new Cookie(MESSAGE_ID, id);
				setCookie(cookie, null, -1, response);
			} else {
				setCookie(cookie, id, -1, response);
			}
		}
	}

	private void setCookie(Cookie cookie, String value, int maxAge, HttpServletResponse resp) {
		cookie.setMaxAge(maxAge);
		cookie.setHttpOnly(true);
		if (value != null) {
			cookie.setValue(value);
		}
		cookie.setPath("/" + urlHelper.getContextPath());
		cookie.setDomain(urlHelper.getDomain());
		resp.addCookie(cookie);
	}

}

考虑到AbstractFlashMapManager本身做了同步处理,因此这里的ConcurrentHashMap可能可以被HashMap来替代。


搜索