设为首页 收藏本站
查看: 1910|回复: 0

[经验分享] 将session放到memcache上面

[复制链接]

尚未签到

发表于 2015-11-18 09:13:29 | 显示全部楼层 |阅读模式
  参考资料:
  http://www.cnblogs.com/Alexander-Lee/archive/2010/06/27/1766229.html


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


  http://blog.iyunv.com/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解决方案




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





使用memcache实现session共享


http://blog.iyunv.com/jimmy1980/article/details/4975476



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



http://blog.iyunv.com/jimmy1980/article/details/4981410



nutz的动作链:
http://blog.iyunv.com/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=&quot;&quot;;
/**
* 设定这个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); // 取摘要,默认是&quot;MD5&quot;算法
// 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 & 0xf0) >> 4);
byte b2 = (byte) (bytes & 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(&quot;MD5&quot;);
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=&quot;&quot;;
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(&quot;&quot;);
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(&quot;testkey&quot;,&quot;您好吗?&quot;);
String str=cache.get(&quot;testkey&quot;).toString();
System.out.println(str);
System.out.println(cache.get(&quot;testkey2&quot;));
}
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注册:
{
&quot;default&quot; : {
&quot;ps&quot; : [
&quot;EWeb.MemCachedSession.SessionBeginProcessor&quot;,//处理session,负责寻找或分配sessionid,创建session等
&quot;org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.EncodingProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.ModuleProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.ActionFiltersProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.AdaptorProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.MethodInvokeProcessor&quot;,
&quot;org.nutz.mvc.impl.processor.ViewProcessor&quot;,
&quot;EWeb.MemCachedSession.SessionEndProcessor&quot;  //将该请求的session写入缓存服务器里面。
],
&quot;error&quot; : '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={&quot;default-chains.js&quot;})
public class MainModule {
@At(&quot;/hello&quot;)
@Ok(&quot;jsp:jsp.sayhello&quot;)
public String sayHello(){
Object ob1=&quot;&quot;;
return &quot;hello!!!!&quot;;
}
}




大功告成。  

版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-140559-1-1.html 上篇帖子: PHP中memcache扩展的三种安装方法 下篇帖子: memcache缓存命中率分析
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表