将session放到memcache上面

参考资料:

http://www.cnblogs.com/Alexander-Lee/archive/2010/06/27/1766229.html

http://tuhaitao.iteye.com/blog/706239

http://blog.csdn.net/kongqz/article/details/7872191


如何构建Java Web应用的session框架

http://imtiger.net/blog/2012/05/10/how-to-build-a-session-framework-for-java-web-application/

http://www.cnblogs.com/xuanfeng/archive/2009/06/04/1494735.html

http://blog.csdn.net/jimmy1980/article/details/4975476


http://blog.csdn.net/jimmy1980/article/details/4981410

nutz的动作链:
http://blog.csdn.net/cdnight/article/details/19010081

好了,经过几天,终于有头绪了。下面就是具体实现:

package EWeb.MemCachedSession;

import java.util.HashMap;
import java.util.Map;

public class MemSession
{
    //会话ID
    private String sid = "";
    //存放本会话的所有信息
    private HashMap<String,String> _map=null;
    protected MemSession(String sessionID){
        _map=new HashMap<String, String>();
        sid=sessionID;
    }
    private boolean _initStatus=true;
    private String _initMsg="";
    /**
     * 设定这个session时候是否出现问题。
     * */
    public void setInitStatus(boolean status,String _msg){

        _initMsg=_msg;
        _initStatus=status;
    }
    public boolean getInitStatus(){
        return _initStatus;
    }
    public String getInitMsg(){
        return _initMsg;
    }
    protected MemSession(String sessionID,HashMap<String,String> __map){
        _map=__map;
        sid=sessionID;
    }
    public String getSessionID(){
        return sid;
    }
    protected HashMap<String,String> getMap(){
        return _map;
    }
    public String getAttribute(String key){
      if(_map.containsKey(key)){
          return _map.get(key);
      }
        return null;
    }
    public boolean setAttribute(String key,String value){
         if(_map.containsKey(key)){
             _map.remove(key);
         }
        _map.put(key,value);
        return true;
    }
    public boolean removeAttribute(String key){
        if(_map.containsKey(key)){
            _map.remove(key);
            return true;
        }
        return false;
    }
    public boolean hasAttribute(String key){
        return _map.containsKey(key);
    }

}



package EWeb.MemCachedSession;
import EWeb.Config.SessionConfig;
import EWeb.MemCacheClient.MemCachedManager;
import Easis.Common.StringUtil;
import Easis.HTTP.CookieHelper;
import Easis.HTTP.CookieUnit;
import com.alibaba.fastjson.JSON;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
public class SessionManager {
    private static final String _session_cookie_key=SessionConfig.sessionKeyInCookie();
    private static final String _session_request_key=SessionConfig.getSessionRequestKey();
    private static final int _session_expires=SessionConfig.sessionExpired();

    private static final int SESSION_ID_BYTES = 16;

    public static synchronized String generateSessionId() {
        // Generate a byte array containing a session identifier
        Random random = new SecureRandom();  // 取随机数发生器, 默认是SecureRandom
        byte bytes[] = new byte[SESSION_ID_BYTES];
        random.nextBytes(bytes); //产生16字节的byte
        bytes = getDigest().digest(bytes); // 取摘要,默认是"MD5"算法

        // Render the result as a String of hexadecimal digits
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {     //转化为16进制字符串
            byte b1 = (byte) ((bytes[i] & 0xf0) >> 4);
            byte b2 = (byte) (bytes[i] & 0x0f);
            if (b1 < 10)
                result.append((char) ('0' + b1));
            else
                result.append((char) ('A' + (b1 - 10)));
            if (b2 < 10)
                result.append((char) ('0' + b2));
            else
                result.append((char) ('A' + (b2 - 10)));
        }

        //--将当前秒数也加上去。

        return (result.toString()+new Date().getTime());

    }
    private static MessageDigest getDigest() {

        try {

            MessageDigest md = MessageDigest.getInstance("MD5");

            return md;

        } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 初始化session,即,判断是否有session,request范围有就一定有,没有就判断cookie的sessionid在不在等等,新建一个session,
     * 然后放进request,以供整个请求期间程序的使用。
     * */
    public static MemSession initSession(HttpServletRequest request){
        HashMap<String,CookieUnit> _cookies= CookieHelper.getCookieMap(request);
        String _current_sessionID="";
        boolean _need_create=false;
        if(!_cookies.containsKey(_session_cookie_key)){
            _need_create=true;
        }
        else{
            String _sessionID=_cookies.get(_session_cookie_key).value;
            if(StringUtil.isNullOrEmpty(_sessionID)){
                _need_create=true;
            }
            else{
                _sessionID=_sessionID.trim();
                if(!MemCachedManager.getInstance().keyExists(_sessionID)){
                    _need_create=true;
                }
            }
        }
        MemSession _session=new MemSession("");
        if(_need_create){
            _current_sessionID=generateSessionId();
            _session=new MemSession(_current_sessionID);
        }
        else{
            _current_sessionID= _cookies.get(_session_cookie_key).value.trim();
            String _res=        MemCachedManager.getInstance().get(_current_sessionID).toString();
            HashMap<String,String> _theMap=new HashMap<String, String>();
            _theMap= (HashMap<String,String>)JSON.parseObject(_res,HashMap.class);
            _session=new MemSession(_current_sessionID,_theMap);
        }
        //--将其保存到整个request请求,确保整个请求期间都可用。

            request.setAttribute(_session_request_key,_session);
        return _session;
    }
    /**
     * 单纯从request里面提取已经保存的MemSession对象。请注意,自定义session机制的使用。
     * */
    public static MemSession getSession(HttpServletRequest request){
        if(request.getAttribute(_session_request_key)==null){
            return null;
        }
        else{
            return (MemSession)request.getAttribute(_session_request_key);
        }
    }

    /**
     * 将MemSession相关内容序列化保存到memcache。
     * */
    protected static boolean saveSessionToCache(MemSession _session){
        if(_session==null||StringUtil.isNullOrEmpty(_session.getSessionID())){
            return false;
        }
        MemCachedManager _cache=MemCachedManager.getInstance();
        if(_cache.keyExists(_session.getSessionID())){
            Calendar _c=Calendar.getInstance();
            _c.add(Calendar.MINUTE,_session_expires/60);
            String res=JSON.toJSONString(_session.getMap());
            _cache.replace(_session.getSessionID(),res,_c.getTime());
            return true;
        }
        else{
            Calendar _c=Calendar.getInstance();
            _c.add(Calendar.MINUTE,_session_expires/60);
            String res=JSON.toJSONString(_session.getMap());
            _cache.add(_session.getSessionID(), res,_c.getTime());
            return true;
        }
    }
    /**
     * 将sessionid作为凭证保存到cookie里面。
     * */
    protected static boolean saveSessionidToCookie(MemSession _session,HttpServletResponse response){
        CookieUnit _cookie=new CookieUnit(_session_cookie_key,_session.getSessionID(),_session_expires,false,true);
        CookieHelper.addCookie(response,_cookie);
        return true;
    }
}


package EWeb.MemCacheClient;
import java.util.Date;

import EWeb.Config.AppConfig;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;

/**
 * 警告:这个类是memcache的客户端,用于帮助存取缓存内容,
 * 要使用请先配置好memcache服务器,并且运行该服务器,
 * 正如要读写数据库时候需要安装数据库并运行数据库服务。
 * */
public class MemCachedManager {
    // 创建全局的唯一实例
    protected static MemCachedClient mcc = new MemCachedClient();

    protected static MemCachedManager memCached = new MemCachedManager();

    // 设置与缓存服务器的连接池
    static {
        // 服务器列表和其权重
        /**
         *这里是根据配置文件读取memcache服务器的ip地址,不够不用这么麻烦,调试状态可以直接设为:127.0.0.1:11211
         */
        String _memcacheServerIP=AppConfig.getMemCachedServerIP();

        String[] servers = {_memcacheServerIP};
        Integer[] weights = { 3 };

        // 获取socke连接池的实例对象
        SockIOPool pool = SockIOPool.getInstance();

        // 设置服务器信息
        pool.setServers( servers );
        pool.setWeights( weights );

        // 设置初始连接数、最小和最大连接数以及最大处理时间
        pool.setInitConn( 5 );
        pool.setMinConn( 5 );
        pool.setMaxConn( 250 );
        pool.setMaxIdle( 1000 * 60 * 60 * 6 );

        // 设置主线程的睡眠时间
        pool.setMaintSleep( 30 );

        // 设置TCP的参数,连接超时等
        pool.setNagle( false );
        pool.setSocketTO( 3000 );
        pool.setSocketConnectTO( 0 );

        // 初始化连接池
        pool.initialize();

        // 压缩设置,超过指定大小(单位为K)的数据都会被压缩

        //mcc.setCompressEnable( true );
       // mcc.setCompressThreshold( 64 * 1024 );
    }

    /**
     * 保护型构造方法,不允许实例化!
     *
     */
    protected MemCachedManager()
    {

    }

    /**
     * 获取唯一实例.
     * @return
     */
    public static MemCachedManager getInstance()
    {
        return memCached;
    }

    /**
     * 添加一个指定的值到缓存中.
     * @param key
     * @param value
     * @return
     */
    public boolean add(String key, Object value)
    {
        return mcc.add(key, value);
    }

    public boolean add(String key, Object value, Date expiry)
    {
        return mcc.add(key, value, expiry);
    }

    public boolean replace(String key, Object value)
    {
        return mcc.replace(key, value);
    }

    public boolean replace(String key, Object value, Date expiry)
    {
        return mcc.replace(key, value, expiry);
    }

    /**
     * 根据指定的关键字获取对象.
     * @param key
     * @return
     */
    public Object get(String key)
    {

        return mcc.get(key);
    }
    public boolean delete(String key){

        return mcc.delete(key);
    }
    public boolean keyExists(String key){
        return mcc.keyExists(key);
    }


    public static void main(String[] args)
    {
        MemCachedManager cache = MemCachedManager.getInstance();
        long startDate=System.currentTimeMillis();
        try{
            cache.add("testkey","您好吗?");
            String str=cache.get("testkey").toString();
            System.out.println(str);
            System.out.println(cache.get("testkey2"));
        }
        catch (Exception ed){
            ed.printStackTrace();
        }
    }
}


下面是针对nutz框架使用的动作链processor:

package EWeb.MemCachedSession;

import org.nutz.mvc.*;
import org.nutz.mvc.impl.processor.AbstractProcessor;

/**
 * 这是自定session在nutz框架上面必须运行的处理器。
 * */
public class SessionBeginProcessor  extends AbstractProcessor {

    public void process(ActionContext ac) throws Throwable {
        MemSession _session= SessionManager.initSession(ac.getRequest());
        SessionManager.saveSessionidToCookie(_session,ac.getResponse());
        doNext(ac);
    }
}


package EWeb.MemCachedSession;


import org.nutz.mvc.ActionContext;
import org.nutz.mvc.impl.processor.AbstractProcessor;

/**
 * 这是自定session在nutz框架上面必须运行的处理器。
 * */
public class SessionEndProcessor extends AbstractProcessor {
    public void process(ActionContext ac) throws Throwable {
        MemSession _session= SessionManager.getSession(ac.getRequest());
        SessionManager.saveSessionToCache(_session);
        doNext(ac);
    }
}


下面是配置文件及main module注册:
{
    "default" : {
    "ps" : [
        "EWeb.MemCachedSession.SessionBeginProcessor",//处理session,负责寻找或分配sessionid,创建session等
        "org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor",
        "org.nutz.mvc.impl.processor.EncodingProcessor",
        "org.nutz.mvc.impl.processor.ModuleProcessor",
        "org.nutz.mvc.impl.processor.ActionFiltersProcessor",
        "org.nutz.mvc.impl.processor.AdaptorProcessor",
        "org.nutz.mvc.impl.processor.MethodInvokeProcessor",
        "org.nutz.mvc.impl.processor.ViewProcessor",
        "EWeb.MemCachedSession.SessionEndProcessor"  //将该请求的session写入缓存服务器里面。
    ],
        "error" : 'org.nutz.mvc.impl.processor.FailProcessor'
}
}


package EWeb.Controller;

import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.ChainBy;
import org.nutz.mvc.annotation.Modules;
import org.nutz.mvc.annotation.Ok;

@Modules(scanPackage=true)
@ChainBy(args={"default-chains.js"})
public class MainModule {
    @At("/hello")
    @Ok("jsp:jsp.sayhello")
    public String sayHello(){
        Object ob1="";

        return "hello!!!!";
    }

}


大功告成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值