参考资料:
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!!!!";
- }
- }
大功告成。