文档章节

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

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


© 著作权归作者所有

共有 人打赏支持
玛雅牛

玛雅牛

粉丝 477
博文 109
码字总数 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
JFinal 3.4 发布,将极速贯彻到 UI 层

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

JFinal ⋅ 04/28 ⋅ 129

JAVA 极速WEB+ORM框架 - JFinal

JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python、p...

JFinal ⋅ 2012/03/18 ⋅ 496

jfinal-oauth2.0-server

基于JFinal,jfinal-ext3 参考RFC6749实现了4.节描述的内容。 实现了OAuth 2.0定义了四种授权方式 授权码模式(authorization code): 先获取下次请求token的code,然后在带着code去请求tok...

Jobsz ⋅ 2015/06/30 ⋅ 0

kiplinglee/jfinal-ioc-plugin

jfinal-ioc-plugin JFinal 依赖注入插件 1.在JFinalConfig文件中配置IOC插件 @Overridepublic void configConstant(Constants me) { // 创建controller实现依赖注入me.setControllerFactory......

kiplinglee ⋅ 04/13 ⋅ 0

基于注释自动生成 API 文档 - Regan API

Regan API 前言 Regan API 项目是基于注释自动生成api文档,很大缩短了开始与后期维护API接口文档的时间。 Regan API 利用jdk提供的Doclet 类读取文档注释,可手动配置需要读取的文件,同时增...

Jeff_Regan ⋅ 06/15 ⋅ 0

JFinal如何使用JNDI连接数据库

想用JNDI的方式连接数据库,但是JFinal中用的是DruidPlugin和ActiveRecordPlugin,没有看到用DataSource的地方?请问JFinal支持JNDI连接方式吗?怎么具体实现?...

zqq3436 ⋅ 06/11 ⋅ 0

Jboot v1.4.9 发布,核心 JFinal 升级到 3.4 最新版本

Jboot 是一个基于 JFinal 和 Undertow 开发的微服务框架。提供了 AOP、RPC、分布式缓存、限流、降级、熔断、统一配置中心、Opentracing 数据追踪、metrics 数据监控、分布式 session、代码生...

理工男海哥 ⋅ 05/03 ⋅ 0

jfinal-admin 3.2 发布,beetl 模板升级到 2.7.14

jfinal-admin 3.2 版本正式发布啦。 基于JFinal的后台管理系统,采用了简洁强大的JFinal作为web框架,模板引擎用的是beetl,数据库用mysql,前端bootstrap框架。 演示地址 http://jad.yxyun...

IT小香猪 ⋅ 04/19 ⋅ 0

JFinal 1.6可以无缝升级到最高哪个版本?

大约在JFinal 1.6的时候做了一个项目,一直运行至今。中途没升级也没做功能扩展,时至今日,需要做功能升级了,但是时隔太久远,基本不记得JFinal这个框架一路过来的升级过程了。所以想请求帮...

车开源 ⋅ 05/11 ⋅ 0

jfinal兼容oracle integer字段

为什么oracle integer字段用了number(3,0),jfinal生成的字段还是BigDecimal @jfinal

tianxia007 ⋅ 05/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CENTOS7防火墙命令记录

安装Firewall命令: yum install firewalld firewalld-config Firewall开启常见端口命令: firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --zone=public --add-po......

cavion ⋅ 50分钟前 ⋅ 0

【C++】【STL】利用chromo来测量程序运行时间与日志时间打印精确到微秒

直接上代码吧,没啥好说的。头疼。 #include <iostream>#include <string>#include <ctime>#include <sstream>#include <iomanip>#include <thread>#include <chrono>using ......

muqiusangyang ⋅ 53分钟前 ⋅ 0

Mac环境下svn的使用

在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还需做一下简...

故久呵呵 ⋅ 今天 ⋅ 0

破解公司回应苹果“USB限制模式”:已攻破

本周四,苹果发表声明称 iOS 中加入了一项名为“USB 限制模式”的功能,可以防止 iPhone 在连接其他设备的时候被破解,并且强调这一功能并不是针对 FBI 等执法部门,为的是保护用户数据安全。...

六库科技 ⋅ 今天 ⋅ 0

MyBtais整合Spring Boot整合,TypeHandler对枚举类(enum)处理

概要 问题描述 我想用枚举类来表示用户当前状态,枚举类由 code 和 msg 组成,但我只想把 code 保存到数据库,查询处理,能知道用户当前状态,这应该怎么做呢?在 Spring 整合MyBatis 的时候...

Wenyi_Feng ⋅ 今天 ⋅ 0

synchronized与Lock的区别

# <center>王梦龙的读书笔记第一篇</center> ## <center>-synchronized与Lock的区别</centre> ###一、从使用场景来说 + synchronized 是能够注释代码块、类、方法但是它的加锁是和解锁使用一......

我不想加班 ⋅ 今天 ⋅ 0

VConsole的使用

手机端控制台打印输出,方便bug的排查。 首先需要引入vconsole.min.js 文件,然后在文件中创造实例。就能直接使用了。 var vConsole = new VConsole(); vConsole的文件地址...

大美琴 ⋅ 今天 ⋅ 0

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 今天 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 今天 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部