您的位置:首页 > 数据库 > Memcache

将session放到memcache上面

2014-02-07 10:03 260 查看
参考资料:
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/

Memcahed分布式缓存服务替换Session解决方案

/article/4846370.html

使用memcache实现session共享

/article/10939546.html

Memcache存储session,修改tomcat源码,实现全站二级域名session共享

/article/10939547.html

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!!!!";
}

}


大功告成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: