package com.jiuqi.mobile.core.service.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.server.session.ISession; import com.jqmobile.core.utils.timer.BaseTimer; import com.jqmobile.core.utils.timer.TimerTask; /** * 基于Servlet的Session实例实现 * @author MODI * * @project com.jiuqi.mobile.service * @date 2013年11月19日 */ public abstract class Session extends TimerTask<Void, Boolean> implements ISession{ /** * Session绑定释放 */ abstract void release1(); private Session(){ timer.add(this); } static{ // openAutoInvalidate(); } private static final int DefaultMaxInactiveInterval = 30*60000; private static final String SESSION_ID=HttpUtils.REQUEST_SESSION; private final static Map<String, SessionImpl> map = Collections.synchronizedMap(new HashMap<String, SessionImpl>()); private final static Map<Long, SessionImpl> haveMap = Collections.synchronizedMap(new HashMap<Long, SessionImpl>()); private final static BaseTimer timer = BaseTimer.instance(180000); public static Session getSession(){ SessionImpl session = haveMap.get(Thread.currentThread().getId()); if(null == session){//针对Struts2框架整合处理 try{ HttpServletRequest request = ServletActionContext.getRequest(); Object obj = request.getSession().getAttribute(SESSION_ID); if(null != obj && obj instanceof String){ session = map.get(obj); if(null != session && !session.isBusy){ session.activate(request); // synchronized (haveMap) { // haveMap.put(Thread.currentThread().getId(), session); // } } } }catch(Throwable e){ } } if(null != session) session.f5lastAccessedTime(); return session; } /** * 激活Session(持有Session) * @param request */ public static void activate_(HttpServletRequest request){ if(null != request){ Object obj = request.getSession().getAttribute(SESSION_ID); if(null != obj && obj instanceof String){ SessionImpl session = map.get(obj); if(null != session && !session.isBusy){ session.activate(request); synchronized (haveMap) { haveMap.put(Thread.currentThread().getId(), session); } return; } } } SessionImpl si = new SessionImpl(request); if(null != request) request.getSession().setAttribute(SESSION_ID, si.getId()); map.put(si.getId(), si); si.activate(request); synchronized (haveMap) { haveMap.put(Thread.currentThread().getId(), si); } } /** * 激活Session(持有Session) * @param request */ public static void activate_(String sessionId){ if(null != sessionId){ SessionImpl session = map.get(sessionId); if(null != session){ session.activate(null); synchronized (haveMap) { haveMap.put(Thread.currentThread().getId(), session); } return; }else{ throw new SessionExceedTimeException(sessionId); } } // SessionImpl si = new SessionImpl(null); // map.put(si.getId(), si); // synchronized (haveMap) { // haveMap.put(Thread.currentThread().getId(), si); // } } /** * 释放Session */ public static void release_(){ Session session = getSession(); if(null != session){ session.release1(); haveMap.remove(Thread.currentThread().getId()); } } /** * 销毁Session */ public static void invalidate_(){ Session session = getSession(); if(null != session){ session.invalidate(); haveMap.remove(Thread.currentThread().getId()); } } public static void setUserId(String userId){ Session session = getSession(); if(null != session && session instanceof SessionImpl){ ((SessionImpl)session).setUserId_(userId); } } //=================================== // private static boolean TimerTaskBusy = false; // private final static ITimerTask<Void> timerTask = new ITimerTask<Void>() { // // @Override // public long period() { // return 180000;//3分钟 // } // // @Override // public void onResult(Void result) throws Throwable { // } // // @Override // public Void onHandler() throws Throwable { // if(TimerTaskBusy){ // return null; // } // TimerTaskBusy = true; // try{ // List<Session> clearList = new ArrayList<Session>(); // synchronized (map) { // for(Session s : map.values()){ // if(s.canAutoColose()){ // clearList.add(s); // } // } // } // for(Session s : clearList){ // s.invalidate(); // } // }finally{ // TimerTaskBusy = false; // } // return null; // } // // @Override // public void onException(Throwable e) { // // } // // @Override // public long delay() { // return 3000; // } // // @Override // public long id() { // return 0; // } // }; // private static void openAutoInvalidate(){ // ITimerPool pool = BaseTimerPool.getInstance(1); // pool.putTask(timerTask); // } @Override protected Boolean doInBackground(Void... params) throws Throwable { return canAutoColose(); } @Override protected void onPostExecute(Boolean result) { if(result){ invalidate(); } } @Override protected long delay() { return 3000; } @Override protected long period() { return 600000;//十分钟 } private boolean canAutoColose() { return System.currentTimeMillis()-getLastAccessedTime()>=getMaxInactiveInterval(); } @Override public String toString() { return "session:"+getId(); } //=================================== static class SessionImpl extends Session{ private final long creationTime = System.currentTimeMillis(); private final String id = UUID.randomUUID().toString(); private long lastAccessedTime = creationTime; private HttpServletRequest request; private int maxInactiveInterval = DefaultMaxInactiveInterval; private final Map<String, Object> map = new HashMap<String, Object>(); private boolean isNew = true; private boolean isBusy = false; private final Object lock = new Object(); private String userId; public SessionImpl(HttpServletRequest request){ this.request = request; } void activate(HttpServletRequest request){ synchronized (lock) { while(isBusy){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); continue; } } } this.request = request; f5lastAccessedTime(); isBusy = true; if(isNew) isNew = false; } void release1(){ f5lastAccessedTime(); isBusy = false; synchronized (lock) { lock.notifyAll(); } } private void f5lastAccessedTime() { lastAccessedTime = System.currentTimeMillis(); } @Override public long getCreationTime() { return this.creationTime; } @Override public String getId() { return this.id; } @Override public long getLastAccessedTime() { return this.lastAccessedTime; } @Override public HttpServletRequest getHttpServletRequest() { return this.request; } @Override public void setMaxInactiveInterval(int interval) { this.maxInactiveInterval = interval; } @Override public int getMaxInactiveInterval() { return maxInactiveInterval; } @Override public Object getAttribute(String name) { synchronized (map) { map.get(name); } return null; } @Override public void setAttribute(String name, Object value) { synchronized (map) { map.put(name, value); } } @Override public void removeAttribute(String name) { synchronized (map) { map.remove(name); } } @Override public void invalidate() { synchronized (map) { map.remove(getId()); } onCancelled(); } @Override public boolean isNew() { return isNew; } @Override public String getUserId() { return userId; } private void setUserId_(String userId) { this.userId = userId; } } }