给JFinal添加了类似ROR的Flash功能-第二版实现。
给JFinal添加了类似ROR的Flash功能-第二版实现。
玛雅牛 发表于4年前
给JFinal添加了类似ROR的Flash功能-第二版实现。
  • 发表于 4年前
  • 阅读 1129
  • 收藏 13
  • 点赞 2
  • 评论 3

腾讯云 十分钟定制你的第一个小程序>>>   

前几天做了第一版。收到了一些反馈,昨天对代码进行重构,比第一版更灵活一些,除了基于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"));
}
使用方式同第一版实现。


标签: JFinal Flash
共有 人打赏支持
玛雅牛
粉丝 467
博文 102
码字总数 24777
作品 4
评论 (3)
菜根乱谭
期待jfinal框架支持该功能,暂且不在我的平台中增加这个了,要加快啊。@JFinal
Jacky_D_H
Flash interceptor:
String curAction = ai.getViewPath()+ai.getMethodName();
这里使用viewpath+methodName有问题,会导致找不到前面保存的session。
应该用ai.getActionKey();
玛雅牛

引用来自“Jacky_D_H”的评论

Flash interceptor:
String curAction = ai.getViewPath()+ai.getMethodName();
这里使用viewpath+methodName有问题,会导致找不到前面保存的session。
应该用ai.getActionKey();
多谢多谢,我看看。
×
玛雅牛
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: