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