文档章节

给JFinal添加了类似ROR的Flash功能-第二版实现。

玛雅牛
 玛雅牛
发布于 2013/06/07 20:34
字数 1030
阅读 1176
收藏 13

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


© 著作权归作者所有

共有 人打赏支持
玛雅牛

玛雅牛

粉丝 484
博文 113
码字总数 27360
作品 4
高级程序员
私信 提问
加载中

评论(3)

玛雅牛
玛雅牛

引用来自“Jacky_D_H”的评论

Flash interceptor:
String curAction = ai.getViewPath()+ai.getMethodName();
这里使用viewpath+methodName有问题,会导致找不到前面保存的session。
应该用ai.getActionKey();
多谢多谢,我看看。
Jacky_D_H
Jacky_D_H
Flash interceptor:
String curAction = ai.getViewPath()+ai.getMethodName();
这里使用viewpath+methodName有问题,会导致找不到前面保存的session。
应该用ai.getActionKey();
菜根乱谭
菜根乱谭
期待jfinal框架支持该功能,暂且不在我的平台中增加这个了,要加快啊。@JFinal
ROR 的flash功能什么时候加入到jfinal?

@JFinal 你好,想跟你请教个问题: 波总,请问有没有计划把ROR的flash功能加入到jfinal里? Thanks.

Jacky_D_H
2015/05/04
115
1
JFinal的ActiveRecord有更详细的文档吗?

因为也在尝试用Java实现类似RoR的ActiveRecord,就想看看现有框架都实现了哪些特性。 看了JFinal 1.5的手册,感觉写得太简短,例如Dialect的使用只提供了如何创建Dialect的方法,没指出Diale...

redraiment
2014/04/25
329
5
JFinal 3.1 发布,没有繁琐、没有复杂,只有妙不可言

JFinal 3.1 针对 3.0 版推出的魔板引擎进行了深度打磨,例如魔板 parse 异常提示更加友好明确,消除指令嵌套时多出来的一个换行符,对于模板 isModified() 逻辑进行了重构,消除冗余代码,可...

JFinal
2017/05/04
17.1K
181
JFinal-Code-Online 1.0 发布,极简自由的代码生成器

定制属于自己的代码生成器从JFinal-Code-Online Platform(JCOP)开始!! JCOP是一个轻量级的代码生成器内核,可加入一切自己想生成的文件的模板,绝对的灵活自由,你值得拥有!! JCOP基于Java,JFin...

绝望的八皮
2015/01/06
7.9K
88
JFinal 3.5 发布,将能上的菜先上了

jfinal 新功能经过 6 个月的酝酿、开发,在大幅度的创新来临之前,jfinal 3.5 这一版先稳一稳,趁着国庆长假,将能上的菜先上了。 jfinal 3.5 这一版针对这 6 个月以来用户反馈最强烈、最频繁...

JFinal
2018/10/08
10.8K
134

没有更多内容

加载失败,请刷新页面

加载更多

centos7重置密码、单用户模式、救援模式、ls命令、chmod命令

在工作当中如果我们错误的配置了文件使服务器不能正常启动或者忘记密码不能登录系统,如何解决这些问题呢?重装系统是可以实现的,但是往往不能轻易重装系统的,下面用忘记密码作为例子讲解如...

李超小牛子
今天
3
0
Python如何开发桌面应用程序?Python基础教程,第十三讲,图形界面

当使用桌面应用程序的时候,有没有那么一瞬间,想学习一下桌面应用程序开发?行业内专业的桌面应用程序开发一般是C++,C#来做,Java开发的也有,但是比较少。本节课会介绍Python的GUI(图形用...

程序员补给栈
今天
5
0
kafka在的使用

一、基本概念 介绍 Kafka是一个分布式的、可分区的、可复制的消息系统。它提供了普通消息系统的功能,但具有自己独特的设计。 这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统...

狼王黄师傅
今天
3
0
Android JNI总结

0x01 JNI介绍 JNI是Java Native Interface的缩写,JNI不是Android专有的东西,它是从Java继承而来,但是在Android中,JNI的作用和重要性大大增强。 JNI在Android中起着连接Java和C/C++层的作...

天王盖地虎626
昨天
3
0
大数据教程(11.8)Hive1.2.2简介&初体验

上一篇文章分析了Hive1.2.2的安装,本节博主将分享Hive的体验&Hive服务端和客户端的使用方法。 一、Hive与hadoop直接的关系 Hive利用HDFS存储数据,利用MapReduce查询数据。 二、Hive与传统数...

em_aaron
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部