前几天做了第一版。收到了一些反馈,昨天对代码进行重构,比第一版更灵活一些,除了基于ehcache的实现外,还实现了基于Session的实现。
放代码。
package com.jfinal.flash; import java.util.Map; import javax.servlet.http.HttpSession; /** * flash管理器接口。 * @author dafei */ public interface IFlashManager { /** * 添加flash信息到缓存中。 * * @param sessionKey * session路径 * @param curAction * 当前ActionPath * @param key * 键 * @param value * 值 */ public void setFlash(HttpSession session, String curAction, String key, Object value); /*** * 在调用redirect forwardAction * 时回调此接口,将以当前actionPath为key更替为下一个请求actionPath作为key。 * * @param sessionKey * session的Id值 * @param curAction * 当前ActionPath * @param nextAction * 下一个ActionPath */ public void updateFlashKey(HttpSession session, String curAction, String nextAction); /** * 从cache中取得Flash的Map * * @param sessionKey * session路径 * @param curAction * 当前ActionPath * @return Flash的Map */ public Map<String, Object> getFlash(HttpSession session, String curAction); }基于Session的实现
package com.jfinal.ext.flash; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpSession; import com.jfinal.flash.IFlashManager; /** * * 基于Session实现的Flash管理器 * * @author dafei * */ public class SessionFlashManager implements IFlashManager{ /** *默认存储session前缀 */ private final static String sessionKeyPrefix = "_flash_"; /** * 构造函数 */ public SessionFlashManager() { } @SuppressWarnings("unchecked") public void setFlash(HttpSession session, String curAction, String key, Object value) { String sessionKey = sessionKeyPrefix + curAction.replace("/", "_"); Object obj = session.getAttribute(sessionKey); Map<String, Object> map = null; if (obj != null) { map = (Map<String, Object>) obj; } else { map = new ConcurrentHashMap<String, Object>(); session.setAttribute(sessionKey, map); } map.put(key, value); } public void updateFlashKey(HttpSession session, String curAction, String nextAction) { String oldKey = sessionKeyPrefix + curAction.replace("/", "_"); String newkey = sessionKeyPrefix + nextAction.replace("/", "_"); Object obj = session.getAttribute(oldKey); if (obj != null) { session.removeAttribute(oldKey); session.setAttribute(newkey, obj); } } @SuppressWarnings("unchecked") public Map<String, Object> getFlash(HttpSession session, String curAction) { String sessionActionKey = sessionKeyPrefix + curAction.replace("/", "_"); Map<String, Object> map = null; Object obj = session.getAttribute(sessionActionKey); if (obj != null) { map = (Map<String, Object>) obj; session.removeAttribute(sessionActionKey); } return map; } }
基于Ehcache的实现。
package com.jfinal.ext.flash; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpSession; import com.jfinal.flash.IFlashManager; import com.jfinal.kit.StringKit; import com.jfinal.plugin.ehcache.CacheKit; /** * * 基于ehcache实现的Flash管理器 * * @author dafei * */ public class EhCacheFlashManager implements IFlashManager{ /** * ehcache 中的cache名称。 */ private final String flashCacheName; /** * 锁 */ private ReentrantLock lock = new ReentrantLock(); /** * 构造函数 * @param flashCacheName ehcache 中的cache名称。 */ public EhCacheFlashManager(String flashCacheName ) { if (StringKit.isBlank(flashCacheName)){ throw new IllegalArgumentException("flashCacheName can not be blank."); } this.flashCacheName = flashCacheName; } @SuppressWarnings("unchecked") public void setFlash(HttpSession session, String curAction, String key, Object value) { String sessionKey = session.getId(); sessionKey = sessionKey + curAction.replace("/", "_"); lock.lock(); Object obj = CacheKit.get(flashCacheName, sessionKey); Map<String, Object> map = null; if (obj != null) { map = (Map<String, Object>) obj; } else { map = new ConcurrentHashMap<String, Object>(); CacheKit.put(flashCacheName, sessionKey, map); } lock.unlock(); map.put(key, value); } public void updateFlashKey(HttpSession session, String curAction, String nextAction) { String sessionKey = session.getId(); String oldKey = sessionKey + curAction.replace("/", "_"); String newkey = sessionKey + nextAction.replace("/", "_"); lock.lock(); Object obj = CacheKit.get(flashCacheName, oldKey); if (obj != null) { CacheKit.remove(flashCacheName, oldKey); CacheKit.put(flashCacheName, newkey, obj); } lock.unlock(); } @SuppressWarnings("unchecked") public Map<String, Object> getFlash(HttpSession session, String curAction) { String sessionKey = session.getId(); String sessionActionKey = sessionKey + curAction.replace("/", "_"); Map<String, Object> map = null; lock.lock(); Object obj = CacheKit.get(flashCacheName, sessionActionKey); if (obj != null) { map = (Map<String, Object>) obj; CacheKit.remove(flashCacheName, sessionActionKey); } lock.unlock(); return map; } }
装配,修改了Constants类,添加以下代码。
/** * 默认采用session来实现。 */ private IFlashManager flashManager = new SessionFlashManager(); public IFlashManager getFlashManager() { return flashManager; } public void setFlashManager(IFlashManager flashManager) { this.flashManager = flashManager; }
为了方便调用,修改了Controller,定义了两个变量。
初始化部分
private boolean setFlashFalg = false; private IFlashManager flashManager; void init(HttpServletRequest request, HttpServletResponse response, String urlPara) { this.request = request; this.response = response; this.urlPara = urlPara; flashManager = Config.getConstants().getFlashManager(); } public IFlashManager getFlashManager(){ return this.flashManager; }
修改了Controller的其他代码
public String parsePath(String currentActionPath, String url){ if(url.startsWith("/")){//完整路径 return url.split("\\?")[0]; }else if(!url.contains("/")){//类似于detail的路径。 return "/"+ currentActionPath.split("/")[1] + "/" + url.split("\\?")[0]; }else if(url.contains("http:")|| url.contains("https:")){ return null; } ///abc/def","bcd/efg?abc return currentActionPath + "/" + url.split("\\?")[0]; } public void setFlash(String key, Object value){ String actionPath = this.request.getRequestURI(); flashManager.setFlash(this.getSession(false),actionPath, key, value); setFlashFalg = true; } public void forwardAction(String actionUrl) { if(setFlashFalg){//若有新加入的Flash。更换key。 String actionPath = this.request.getRequestURI(); //将以当前actionPath为key更替为下一个请求actionPath作为key flashManager.updateFlashKey(this.getSession(false), actionPath, actionUrl); setFlashFalg =false; } render = new ActionRender(actionUrl); } public void redirect(String url) { if(setFlashFalg){ String actionPath = this.request.getRequestURI(); String newActionPath = parsePath(actionPath, url); flashManager.updateFlashKey(this.getSession(false), actionPath, newActionPath); setFlashFalg = false; } render = renderFactory.getRedirectRender(url); } /** * Redirect to url */ public void redirect(String url, boolean withQueryString) { if(setFlashFalg){ String actionPath = this.request.getRequestURI(); String newActionPath = parsePath(actionPath, url); flashManager.updateFlashKey(this.getSession(false), actionPath, newActionPath); setFlashFalg = false; } render = renderFactory.getRedirectRender(url, withQueryString); }
新增加了一个拦截器。
public class Flash implements Interceptor{ @Override /** * 该拦截器取得当前ActionPath,从Cache中检查是否有传送给当前Action的Flash对象Map * 若有,则遍历Map,并将所有key,value注入到当前的request请求中。 */ public void intercept(ActionInvocation ai) { Controller c = ai.getController(); HttpSession session = c.getSession(false); if(null == session){ return; } String curAction = ai.getViewPath()+ai.getMethodName(); Map<String, Object> flashMap = c.getFlashManager().getFlash(session, curAction); if(flashMap != null){ for(Entry<String,Object> flashEntry: flashMap.entrySet()){ c.setAttr(flashEntry.getKey(), flashEntry.getValue()); } } ai.invoke(); } }
调用初始化,不设定时,默认采用基于session的实现方式。
public void configConstant(Constants me) { //加载数据库配置文件 loadPropertyFile("database.properties"); //设定采用httl模板引擎 me.setMainRenderFactory(new HttlRenderFactory()); me.setFlashManager(new EhCacheFlashManager("flashCache")); }使用方式同第一版实现。