文档章节

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

玛雅牛
 玛雅牛
发布于 2013/06/07 20:34
字数 1030
阅读 1166
收藏 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"));
}
使用方式同第一版实现。


© 著作权归作者所有

共有 人打赏支持
玛雅牛

玛雅牛

粉丝 479
博文 113
码字总数 27287
作品 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
OSC上关于Jfinal的提问整理(一)

看见Jfinal很火,就手痒痒了,想学一下,无奈入门较慢,没有找到比较全的文档。于是就经常看讨论区大家的提问与解答。后来就忽然萌生了整理下来的想法。其中的问题如果是@Jfinal 回答的,那我...

木川瓦兹
2013/04/23
0
21
JFinal极速开发实战教程新鲜出炉~

JFinal极速开发实战教程新鲜出炉~ [持续更新中...] JFinal框架让 IT 工程师发挥更大的潜能,实现更大价值,同时也希望 JFinal 工具力量能帮助正在创业的朋友们提升效率、降低成本从而实现创业...

山东-小木
2015/01/07
0
13
JFinal 3.4 发布,将极速贯彻到 UI 层

jfinal 的终极目标是全面实现软件开发整个过程的极速开发,极大提升开发效率,极大降低学习成本,极大提升开发体验 jfinal 诞生头五年,已实现 WEB + ORM + AOP 层面的极速开发,赢得了大量开...

JFinal
04/28
0
129
给JFinal添加Shiro插件功能,支持Shiro所有注解-实现篇

2015年8月3日更新: 支持JFinal 2.0 版本,同时给出了一些实际代码,想见git @JFinal给出了一些好的建议,已重构部分代码。 代码放在oschina的git上,访问地址: http://git.oschina.net/mya...

玛雅牛
2013/06/12
0
8
JFinal Weixin 2.1 发布,微信极速 SDK

JFinal Weixin 发布四年多以来,以其简单性、稳定性,获得了大量用户的喜爱,这四年多以来 JFinal Weixin 紧跟微信官方动态,不断增加、完善功能,例如跟随本次微信官方发布的 XXE 漏洞,第一...

JFinal
07/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

这些Spring中的设计模式,你都知道吗?

设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆。 Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行...

Java填坑之路
31分钟前
1
0
Spring Aop原理之Advisor过滤

在上文(Spring Aop之Advisor解析)中我们讲到,Spring Aop对目标bean的代理主要分为三个步骤:获取所有的Advisor,过滤当前bean可应用的Advisor和使用Advisor为当前bean生成代理对象,并且上文...

爱宝贝丶
42分钟前
0
0
JMockit学习教程

1 JMockit中文网 我觉得如果仅仅是开发自测的话,把JMockit中文网认真看一遍,就可以在项目中使用JMockit了。 http://jmockit.cn/index.htm 2 JMockit中文教程 官方文档中文版。对于不喜欢看...

SuperHeroes
53分钟前
0
0
Linux服务器几乎从不采用Arch Linux?

我们见得多的Linux服务器系统一般都是什么Ubuntu Server啊,什么Cent OS啊,什么Fedora啊,或者企业采用的Red Hat啊,为什么几乎没有Arch Linux呢?下面我将从若干个方面指出Arch Linux在服务...

linux-tao
今天
0
0
js 函数柯里化 闭包

参考 https://mp.weixin.qq.com/s/GEHL3jarDdAAcr5tQGjmDg 一个统计求和的函数 需要知道整个数组的信息,然后遍历求值 function countMoney() { let money = 0 // 温馨提示:arguments...

阿豪boy
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部