package com.jqmobile.core.server.session; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.jqmobile.core.http.HttpUtils; import com.jqmobile.core.http.SessionExceedTimeException; import com.jqmobile.core.http2.HttpException; import com.jqmobile.core.utils.timer.TimerTask; public abstract class Session extends TimerTask<Void, Boolean> implements ISession{ private static final int DefaultMaxInactiveInterval = 30*60000; private static final String SESSION_ID=HttpUtils.REQUEST_SESSION; private final static Map<String, Session> map = Collections.synchronizedMap(new HashMap<String, Session>()); public static Session getSession(){ String sessionId = getSessionId(); if(null == sessionId){ throw new SessionExceedTimeException("servlet session中找不到Session id, 请确认session已激活 或 struts框架使用正确"); } Session session = map.get(sessionId); if(null == session){ throw new SessionExceedTimeException(sessionId); } session.f5LastAccessedTime(); return session; } public static void vali(String sessionId, HttpServletRequest request) throws HttpException{ Session session = map.get(sessionId); if(null == session){ throw new HttpException(HttpException.SESSION_TIMEOUT); }else{ session.f5LastAccessedTime(); } sessionid.set(session.getId()); session.servlet = request; } private final static ThreadLocal<String> sessionid = new ThreadLocal<String>(); private static String getSessionId() { String str = sessionid.get(); if(null == str){ try{ HttpServletRequest request = ServletActionContext.getRequest(); str = (String) request.getSession().getAttribute(SESSION_ID); }catch(Throwable e){ e.printStackTrace(); } } return str; } /** * 激活Session(持有Session) * @param request */ public static void activate(HttpServletRequest request){ Session session=null; Object obj = null; if(null != request) obj = request.getSession().getAttribute(SESSION_ID); if(null != obj && obj instanceof String){ session = map.get(obj); if(null != session){ synchronized (session.lock) { while(null != session.servlet){ try { System.err.println("session lock,servlet request : "+session.servlet); System.err.println("this servlet request is : "+request); session.lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } session.f5LastAccessedTime(); } } if(null == session){ session = new BaseSessionImpl(); map.put(session.getId(), session); session.execute(); if(null != request){ request.getSession().setAttribute(SESSION_ID, session.getId()); request.getSession().setMaxInactiveInterval(session.getMaxInactiveInterval()); } } sessionid.set(session.getId()); session.servlet = request; } /** * 释放Session */ public static void release(){ Session session = null; try{ session = getSession(); }catch(Throwable e){ } if(null != session){ session.release_(); sessionid.remove(); } } private void release_() { this.isNew = false; this.servlet = null; this.f5LastAccessedTime(); synchronized (this.lock) { this.lock.notify(); } } public int getTimeOut(){ return maxInactiveInterval; } //================================================ private long lastAccessedTime=System.currentTimeMillis(); private int maxInactiveInterval=DefaultMaxInactiveInterval; private boolean isNew = true; private String userId; private HttpServletRequest servlet; private final Object lock = new Object(); private Session(){ } /** * 刷新最后一次访问时间 */ private void f5LastAccessedTime(){ this.lastAccessedTime = System.currentTimeMillis(); } /** * 销毁 * (non-Javadoc) * @see com.jqmobile.core.server.session.ISession#invalidate() */ @Override public void invalidate() { //销毁 release_(); map.remove(getId()); onCancelled(); } public void setUserId(String userId){ this.userId = userId; } static class BaseSessionImpl extends Session{ private final long creationTime = System.currentTimeMillis(); private final String id = UUID.randomUUID().toString(); private final Map<String, Object> map = new HashMap<String, Object>(); @Override public long getCreationTime() { return creationTime; } @Override public String getId() { return id; } @Override public long getLastAccessedTime() { return super.lastAccessedTime; } @Override public HttpServletRequest getHttpServletRequest() { return super.servlet; } @Override public void setMaxInactiveInterval(int interval) { super.maxInactiveInterval = interval; if(null != super.servlet){ super.servlet.getSession().setMaxInactiveInterval(getMaxInactiveInterval()); } } @Override public int getMaxInactiveInterval() { return super.maxInactiveInterval; } @Override public Object getAttribute(String name) { return map.get(name); } @Override public void setAttribute(String name, Object value) { map.put(name, value); } @Override public void removeAttribute(String name) { map.remove(name); } @Override public boolean isNew() { return super.isNew; } @Override public String getUserId() { return super.userId; } // @Override protected Boolean doInBackground(Void... params) throws Throwable { return (System.currentTimeMillis()-getLastAccessedTime())>getMaxInactiveInterval(); } @Override protected void onPostExecute(Boolean result) { if(result){ invalidate(); //System.out.println("invalidate session id : "+getId()); } } @Override protected long period() { return getMaxInactiveInterval()/3; } @Override protected void onException(Throwable e) { e.printStackTrace(); } } //========================================test public static void main(String[] args) { for(int i=0; i<1000; i++){ Session.activate(null); System.out.println(Session.getSession().getId()); Session.release(); } int i=0; int mapCount=0; while(true){ try { Thread.sleep(1000); System.out.println("============================= count:\t"+i++); // if(0 == AsyncTask.getThreadCount()){ // conn.close(); //// testTime(); // return; // } int j=0; int c = Session.map.size(); for(Session s : Session.map.values()){ if(c != mapCount){ System.out.println(c); mapCount = c; } if(0==j++%3){ sessionid.set(s.getId()); getSession(); release(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } }